]> git.uio.no Git - u/mrichter/AliRoot.git/blobdiff - PYTHIA6/AliGenPythia.cxx
Coding rule violations corrected.
[u/mrichter/AliRoot.git] / PYTHIA6 / AliGenPythia.cxx
index 63a20d3b5e06c94c19fc0f7070c9310928d65b2e..a488c76033b5caa49d89faa124282ac5a009563a 100644 (file)
 #include <TPDGCode.h>
 #include <TSystem.h>
 #include <TTree.h>
-
 #include "AliConst.h"
 #include "AliDecayerPythia.h"
 #include "AliGenPythia.h"
+#include "AliHeader.h"
 #include "AliGenPythiaEventHeader.h"
 #include "AliPythia.h"
 #include "AliPythiaRndm.h"
 #include "AliRun.h"
+#include "AliStack.h"
+#include "AliRunLoader.h"
+#include "AliMC.h"
+#include "pyquenCommon.h"
 
- ClassImp(AliGenPythia)
+ClassImp(AliGenPythia)
 
 AliGenPythia::AliGenPythia()
                  :AliGenMC()
@@ -48,6 +52,12 @@ AliGenPythia::AliGenPythia()
   fParticles = 0;
   fPythia    = 0;
   fHeader = 0;
+  fReadFromFile = 0;
+  fEventTime = 0.;
+  fInteractionRate = 0.;
+  fTimeWindow = 0.;
+  fEventsTime = 0;
+  fCurSubEvent = 0;
   fDecayer   = new AliDecayerPythia();
   SetEventListRange();
   SetJetPhiRange();
@@ -56,7 +66,12 @@ AliGenPythia::AliGenPythia()
   SetGammaPhiRange();
   SetGammaEtaRange();
   SetPtKick();
+  SetQuench();
+  SetHadronisation();  
+  SetTriggerParticle();
   fSetNuclei = kFALSE;
+  fNewMIS    = kFALSE;
+  fHFoff     = kFALSE;
   if (!AliPythiaRndm::GetPythiaRandom()) 
     AliPythiaRndm::SetPythiaRandom(GetRandom());
 }
@@ -71,6 +86,12 @@ AliGenPythia::AliGenPythia(Int_t npart)
     fName = "Pythia";
     fTitle= "Particle Generator using PYTHIA";
     fXsection  = 0.;
+    fReadFromFile = 0;
+    fEventTime = 0.;
+    fInteractionRate = 0.;
+    fTimeWindow = 0.;
+    fEventsTime = 0;
+    fCurSubEvent = 0;
     SetProcess();
     SetStrucFunc();
     SetForceDecay();
@@ -85,7 +106,6 @@ AliGenPythia::AliGenPythia(Int_t npart)
     // Produced particles  
     fParticles = new TClonesArray("TParticle",1000);
     fHeader = 0;
-    fEventVertex.Set(3);
     SetEventListRange();
     SetJetPhiRange();
     SetJetEtaRange();
@@ -93,7 +113,10 @@ AliGenPythia::AliGenPythia(Int_t npart)
     SetGammaPhiRange();
     SetGammaEtaRange();
     SetJetReconstructionMode();
+    SetQuench();
+    SetHadronisation();
     SetPtKick();
+    SetTriggerParticle();
     // Options determining what to keep in the stack (Heavy flavour generation)
     fStackFillOpt = kFlavorSelection; // Keep particle with selected flavor
     fFeedDownOpt = kTRUE;             // allow feed down from higher family
@@ -104,9 +127,12 @@ AliGenPythia::AliGenPythia(Int_t npart)
     // Pycel
     SetPycellParameters();
     fSetNuclei = kFALSE;
+    fNewMIS    = kFALSE;
+    fHFoff     = kFALSE;
 }
 
 AliGenPythia::AliGenPythia(const AliGenPythia & Pythia)
+    :AliGenMC(Pythia)
 {
 // copy constructor
     Pythia.Copy(*this);
@@ -115,6 +141,57 @@ AliGenPythia::AliGenPythia(const AliGenPythia & Pythia)
 AliGenPythia::~AliGenPythia()
 {
 // Destructor
+  if(fEventsTime) delete fEventsTime;
+}
+
+void AliGenPythia::SetInteractionRate(Float_t rate,Float_t timewindow)
+{
+// Generate pileup using user specified rate
+    fInteractionRate = rate;
+    fTimeWindow = timewindow;
+    GeneratePileup();
+}
+
+void AliGenPythia::GeneratePileup()
+{
+// Generate sub events time for pileup
+    fEventsTime = 0;
+    if(fInteractionRate == 0.) {
+      Warning("GeneratePileup","Zero interaction specified. Skipping pileup generation.\n");
+      return;
+    }
+
+    Int_t npart = NumberParticles();
+    if(npart < 0) {
+      Warning("GeneratePileup","Negative number of particles. Skipping pileup generation.\n");
+      return;
+    }
+
+    if(fEventsTime) delete fEventsTime;
+    fEventsTime = new TArrayF(npart);
+    TArrayF &array = *fEventsTime;
+    for(Int_t ipart = 0; ipart < npart; ipart++)
+      array[ipart] = 0.;
+
+    Float_t eventtime = 0.;
+    while(1)
+      {
+       eventtime += (AliPythiaRndm::GetPythiaRandom())->Exp(1./fInteractionRate);
+       if(eventtime > fTimeWindow) break;
+       array.Set(array.GetSize()+1);
+       array[array.GetSize()-1] = eventtime;
+      }
+
+    eventtime = 0.;
+    while(1)
+      {
+       eventtime -= (AliPythiaRndm::GetPythiaRandom())->Exp(1./fInteractionRate);
+       if(TMath::Abs(eventtime) > fTimeWindow) break;
+       array.Set(array.GetSize()+1);
+       array[array.GetSize()-1] = eventtime;
+      }
+
+    SetNumberParticles(fEventsTime->GetSize());
 }
 
 void AliGenPythia::SetPycellParameters(Float_t etamax, Int_t neta, Int_t nphi,
@@ -146,7 +223,8 @@ void AliGenPythia::Init()
 // Initialisation
     
     SetMC(AliPythia::Instance());
-    fPythia=(AliPythia*) fgMCEvGen;
+    fPythia=(AliPythia*) fMCEvGen;
+    
 //
     fParentWeight=1./Float_t(fNpart);
 //
@@ -181,18 +259,36 @@ void AliGenPythia::Init()
        fPythia->SetMSTP(91,0);
     }
 
- //   fPythia->SetMSTJ(1,2);
+
+    if (fReadFromFile) {
+       fRL  =  AliRunLoader::Open(fFileName, "Partons");
+       fRL->LoadKinematics();
+       fRL->LoadHeader();
+    } else {
+       fRL = 0x0;
+    }
+// Switch off Heavy Flavors on request  
+    if (fHFoff) {
+       fPythia->SetMSTP(58, 3);
+       fPythia->SetMSTJ(45, 3);        
+       for (Int_t i = 156; i <= 160; i++) fPythia->SetMDME(i, 1, 0);
+    }
  //
     fPythia->ProcInit(fProcess,fEnergyCMS,fStrucFunc);
 
 //  Parent and Children Selection
     switch (fProcess) 
     {
+    case kPyOldUEQ2ordered:
+    case kPyOldUEQ2ordered2:
+    case kPyOldPopcorn:
+      break;
     case kPyCharm:
     case kPyCharmUnforced:
     case kPyCharmPbPbMNR:
-    case kPyCharmppMNR:
     case kPyCharmpPbMNR:
+    case kPyCharmppMNR:
+    case kPyCharmppMNRwmi:
        fParentSelect[0] =   411;
        fParentSelect[1] =   421;
        fParentSelect[2] =   431;
@@ -205,10 +301,23 @@ void AliGenPythia::Init()
        fParentSelect[0] =   421;
        fFlavorSelect    =   4; 
        break;
+    case kPyDPlusPbPbMNR:
+    case kPyDPluspPbMNR:
+    case kPyDPlusppMNR:
+       fParentSelect[0] =   411;
+       fFlavorSelect    =   4; 
+       break;
+    case kPyDPlusStrangePbPbMNR:
+    case kPyDPlusStrangepPbMNR:
+    case kPyDPlusStrangeppMNR:
+       fParentSelect[0] =   431;
+       fFlavorSelect    =   4; 
+       break;
     case kPyBeauty:
     case kPyBeautyPbPbMNR:
     case kPyBeautypPbMNR:
     case kPyBeautyppMNR:
+    case kPyBeautyppMNRwmi:
        fParentSelect[0]=  511;
        fParentSelect[1]=  521;
        fParentSelect[2]=  531;
@@ -234,9 +343,13 @@ void AliGenPythia::Init()
        break;
     case kPyMb:
     case kPyMbNonDiffr:
+    case kPyMbMSEL1:
     case kPyJets:
     case kPyDirectGamma:
        break;
+    case kPyW:
+    case kPyZ:
+        break;
     }
 //
 //
@@ -244,17 +357,17 @@ void AliGenPythia::Init()
 //
 //  Configure detector (EMCAL like)
 //
-       fPythia->SetPARU(51, fPycellEtaMax);
-       fPythia->SetMSTU(51, fPycellNEta);
-       fPythia->SetMSTU(52, fPycellNPhi);
+    fPythia->SetPARU(51, fPycellEtaMax);
+    fPythia->SetMSTU(51, fPycellNEta);
+    fPythia->SetMSTU(52, fPycellNPhi);
 //
 //  Configure Jet Finder
 //  
-       fPythia->SetPARU(58,  fPycellThreshold);
-       fPythia->SetPARU(52,  fPycellEtSeed);
-       fPythia->SetPARU(53,  fPycellMinEtJet);
-       fPythia->SetPARU(54,  fPycellMaxRadius);
-       fPythia->SetMSTU(54,  2);
+    fPythia->SetPARU(58,  fPycellThreshold);
+    fPythia->SetPARU(52,  fPycellEtSeed);
+    fPythia->SetPARU(53,  fPycellMinEtJet);
+    fPythia->SetPARU(54,  fPycellMaxRadius);
+    fPythia->SetMSTU(54,  2);
 //
 //  This counts the total number of calls to Pyevnt() per run.
     fTrialsRun = 0;
@@ -273,6 +386,10 @@ void AliGenPythia::Init()
        fDyBoost = 0;
        Warning("Init","SetNuclei used. Use SetProjectile + SetTarget instead. fDyBoost has been reset to 0\n");
     }
+    
+    if (fQuench) {
+       fPythia->InitQuenching(0., 0.1, 0.6e6, 0);
+    }
 }
 
 void AliGenPythia::Generate()
@@ -283,7 +400,7 @@ void AliGenPythia::Generate()
 
     Float_t polar[3]   =   {0,0,0};
     Float_t origin[3]  =   {0,0,0};
-    Float_t p[3];
+    Float_t p[4];
 //  converts from mm/c to s
     const Float_t kconv=0.001/2.999792458e8;
 //
@@ -291,47 +408,76 @@ void AliGenPythia::Generate()
     Int_t jev=0;
     Int_t j, kf;
     fTrials=0;
+    fEventTime = 0.;
+    
+    
 
     //  Set collision vertex position 
-    if(fVertexSmear==kPerEvent) {
-       fPythia->SetMSTP(151,1);
-       for (j=0;j<3;j++) {
-           fPythia->SetPARP(151+j, fOsigma[j]*10.);
-       }
-    } else if (fVertexSmear==kPerTrack) {
-       fPythia->SetMSTP(151,0);
-    }
+    if (fVertexSmear == kPerEvent) Vertex();
+    
 //  event loop    
     while(1)
     {
-       fPythia->Pyevnt();
-       if (gAlice->GetEvNumber()>=fDebugEventFirst &&
-           gAlice->GetEvNumber()<=fDebugEventLast) fPythia->Pylist(1);
-       fTrials++;
+//
+// Produce event
+//
+//
+// Switch hadronisation off
+//
+       fPythia->SetMSTJ(1, 0);
+//
+// Either produce new event or read partons from file
+//     
+       if (!fReadFromFile) {
+           if (!fNewMIS) {
+               fPythia->Pyevnt();
+           } else {
+               fPythia->Pyevnw();
+           }
+           fNpartons = fPythia->GetN();
+       } else {
+           printf("Loading Event %d\n",AliRunLoader::GetRunLoader()->GetEventNumber());
+           fRL->GetEvent(AliRunLoader::GetRunLoader()->GetEventNumber());
+           fPythia->SetN(0);
+           LoadEvent(fRL->Stack(), 0 , 1);
+           fPythia->Pyedit(21);
+       }
        
+//
+//  Run quenching routine 
+//
+       if (fQuench == 1) {
+           fPythia->Quench();
+       } else if (fQuench == 2){
+           fPythia->Pyquen(208., 0, 0.);
+       }
+//
+// Switch hadronisation on
+//
+       fPythia->SetMSTJ(1, 1);
+//
+// .. and perform hadronisation
+//     printf("Calling hadronisation %d\n", fPythia->GetN());
+       fPythia->Pyexec();      
+       fTrials++;
        fPythia->ImportParticles(fParticles,"All");
-
        Boost();
 //
 //
 //
        Int_t i;
        
+
        Int_t np = fParticles->GetEntriesFast();
-       if (np == 0 ) continue;
-// Get event vertex and discard the event if the Z coord. is too big   
-       TParticle *iparticle = (TParticle *) fParticles->At(0);
-       Float_t distz = iparticle->Vz()/10.;
-       if(TMath::Abs(distz)>fCutVertexZ*fOsigma[2]) continue;
+       
+       if (np == 0) continue;
 //
-       fEventVertex[0] = iparticle->Vx()/10.+fOrigin.At(0);
-       fEventVertex[1] = iparticle->Vy()/10.+fOrigin.At(1);
-       fEventVertex[2] = iparticle->Vz()/10.+fOrigin.At(2);
+       
 //
        Int_t* pParent   = new Int_t[np];
        Int_t* pSelected = new Int_t[np];
        Int_t* trackIt   = new Int_t[np];
-       for (i=0; i< np; i++) {
+       for (i = 0; i < np; i++) {
            pParent[i]   = -1;
            pSelected[i] =  0;
            trackIt[i]   =  0;
@@ -342,10 +488,13 @@ void AliGenPythia::Generate()
        Int_t nTkbles = 0;   // Trackable particles
        if (fProcess != kPyMb && fProcess != kPyJets && 
            fProcess != kPyDirectGamma &&
-           fProcess != kPyMbNonDiffr) {
+           fProcess != kPyMbNonDiffr  &&
+           fProcess != kPyMbMSEL1     &&
+           fProcess != kPyW && fProcess != kPyZ &&
+           fProcess != kPyCharmppMNRwmi && fProcess != kPyBeautyppMNRwmi) {
            
-           for (i = 0; i<np; i++) {
-               iparticle = (TParticle *) fParticles->At(i);
+           for (i = 0; i < np; i++) {
+               TParticle* iparticle = (TParticle *) fParticles->At(i);
                Int_t ks = iparticle->GetStatusCode();
                kf = CheckPDGCode(iparticle->GetPdgCode());
 // No initial state partons
@@ -356,38 +505,58 @@ void AliGenPythia::Generate()
                // quark ?
                kf = TMath::Abs(kf);
                Int_t kfl = kf;
+               // Resonance
+
+               if (kfl > 100000) kfl %= 100000;
+               if (kfl > 10000)  kfl %= 10000;
                // meson ?
                if  (kfl > 10) kfl/=100;
                // baryon
                if (kfl > 10) kfl/=10;
-               if (kfl > 10) kfl/=10;
-
                Int_t ipa = iparticle->GetFirstMother()-1;
                Int_t kfMo = 0;
+//
+// Establish mother daughter relation between heavy quarks and mesons
+//
+               if (kf >= fFlavorSelect && kf <= 6) {
+                   Int_t idau = iparticle->GetFirstDaughter() - 1;
+                   if (idau > -1) {
+                       TParticle* daughter = (TParticle *) fParticles->At(idau);
+                       Int_t pdgD = daughter->GetPdgCode();
+                       if (pdgD == 91 || pdgD == 92) {
+                           Int_t jmin = daughter->GetFirstDaughter() - 1;
+                           Int_t jmax = daughter->GetLastDaughter()  - 1;                          
+                           for (Int_t j = jmin; j <= jmax; j++)
+                               ((TParticle *) fParticles->At(j))->SetFirstMother(i+1);
+                       } // is string or cluster
+                   } // has daughter
+               } // heavy quark
                
+
                if (ipa > -1) {
                    TParticle *  mother = (TParticle *) fParticles->At(ipa);
                    kfMo = TMath::Abs(mother->GetPdgCode());
                }
+               
                // What to keep in Stack?
                Bool_t flavorOK = kFALSE;
                Bool_t selectOK = kFALSE;
                if (fFeedDownOpt) {
-                 if (kfl >= fFlavorSelect) flavorOK = kTRUE;
+                   if (kfl >= fFlavorSelect) flavorOK = kTRUE;
                } else {
-                 if (kfl > fFlavorSelect) {
-                   nc = -1;
-                   break;
-                 }
-                 if (kfl == fFlavorSelect) flavorOK = kTRUE;
+                   if (kfl > fFlavorSelect) {
+                       nc = -1;
+                       break;
+                   }
+                   if (kfl == fFlavorSelect) flavorOK = kTRUE;
                }
                switch (fStackFillOpt) {
                case kFlavorSelection:
-                 selectOK = kTRUE;
-                 break;
+                   selectOK = kTRUE;
+                   break;
                case kParentSelection:
-                 if (ParentSelected(kf) || kf <= 10) selectOK = kTRUE;
-                 break;
+                   if (ParentSelected(kf) || kf <= 10) selectOK = kTRUE;
+                   break;
                }
                if (flavorOK && selectOK) { 
 //
@@ -396,7 +565,7 @@ void AliGenPythia::Generate()
 // Kinematic seletion on final state heavy flavor mesons
                    if (ParentSelected(kf) && !KinematicSelection(iparticle, 0)) 
                    {
-                     continue;
+                       continue;
                    }
                    pSelected[i] = 1;
                    if (ParentSelected(kf)) ++nParents; // Update parent count
@@ -404,9 +573,9 @@ void AliGenPythia::Generate()
                } else {
 // Kinematic seletion on decay products
                    if (fCutOnChild && ParentSelected(kfMo) && ChildSelected(kf) 
-                       && !KinematicSelection(iparticle, 1))
+                       && !KinematicSelection(iparticle, 1)) 
                    {
-                     continue;
+                       continue;
                    }
 //
 // Decay products 
@@ -436,6 +605,7 @@ void AliGenPythia::Generate()
                if (!pSelected[i]) continue;
                // Count quarks only if you did not include fragmentation
                if (fFragmentation && kf <= 10) continue;
+
                nc++;
 // Decision on tracking
                trackIt[i] = 0;
@@ -443,7 +613,7 @@ void AliGenPythia::Generate()
 // Track final state particle
                if (ks == 1) trackIt[i] = 1;
 // Track semi-stable particles
-               if ((ks ==1) || (fDecayer->GetLifetime(kf) > fMaxLifeTime))  trackIt[i] = 1;
+               if ((ks == 1) || (fDecayer->GetLifetime(kf) > fMaxLifeTime))  trackIt[i] = 1;
 // Track particles selected by process if undecayed. 
                if (fForceDecay == kNoDecay) {
                    if (ParentSelected(kf)) trackIt[i] = 1;
@@ -464,25 +634,34 @@ void AliGenPythia::Generate()
                    p[0] = iparticle->Px();
                    p[1] = iparticle->Py();
                    p[2] = iparticle->Pz();
-                   origin[0] = fOrigin[0]+iparticle->Vx()/10.;
-                   origin[1] = fOrigin[1]+iparticle->Vy()/10.;
-                   origin[2] = fOrigin[2]+iparticle->Vz()/10.;
+                   p[3] = iparticle->Energy();
+                   
+                   origin[0] = fVertex[0]+iparticle->Vx()/10; // [cm]
+                   origin[1] = fVertex[1]+iparticle->Vy()/10; // [cm]
+                   origin[2] = fVertex[2]+iparticle->Vz()/10; // [cm]
+                   
                    Float_t tof   = kconv*iparticle->T();
                    Int_t ipa     = iparticle->GetFirstMother()-1;
                    Int_t iparent = (ipa > -1) ? pParent[ipa] : -1;
-                   SetTrack(fTrackIt*trackIt[i] ,
-                                    iparent, kf, p, origin, polar, tof, kPPrimary, nt, 1., ks);
+                   PushTrack(fTrackIt*trackIt[i], iparent, kf, 
+                             p[0], p[1], p[2], p[3], 
+                             origin[0], origin[1], origin[2], tof, 
+                             polar[0], polar[1], polar[2],
+                             kPPrimary, nt, 1., ks);
                    pParent[i] = nt;
                    KeepTrack(nt); 
-               } //  SetTrack loop
+               } //  PushTrack loop
            }
        } else {
            nc = GenerateMB();
        } // mb ?
+       
+       GetSubEventTime();
 
-       if (pParent)   delete[] pParent;
-       if (pSelected) delete[] pSelected;
-       if (trackIt)   delete[] trackIt;
+       delete[] pParent;
+       delete[] pSelected;
+       delete[] trackIt;
 
        if (nc > 0) {
          switch (fCountMode) {
@@ -501,8 +680,7 @@ void AliGenPythia::Generate()
          }
            if (jev >= fNpart || fNpart == -1) {
                fKineBias=Float_t(fNpart)/Float_t(fTrials);
-               printf("\n Trials: %i %i %i\n",fTrials, fNpart, jev);
-
+               
                fQ  += fPythia->GetVINT(51);
                fX1 += fPythia->GetVINT(41);
                fX2 += fPythia->GetVINT(42);
@@ -515,7 +693,7 @@ void AliGenPythia::Generate()
     } // event loop
     SetHighWaterMark(nt);
 //  adjust weight due to kinematic selection
-    AdjustWeights();
+//    AdjustWeights();
 //  get cross-section
     fXsection=fPythia->GetPARI(1);
 }
@@ -527,22 +705,80 @@ Int_t  AliGenPythia::GenerateMB()
 //
     Int_t i, kf, nt, iparent;
     Int_t nc = 0;
-    Float_t p[3];
+    Float_t p[4];
     Float_t polar[3]   =   {0,0,0};
     Float_t origin[3]  =   {0,0,0};
 //  converts from mm/c to s
     const Float_t kconv=0.001/2.999792458e8;
     
-    Int_t np = fParticles->GetEntriesFast();
+
+    
+    Int_t np = (fHadronisation) ? fParticles->GetEntriesFast() : fNpartons;
+
+
+
     Int_t* pParent = new Int_t[np];
     for (i=0; i< np; i++) pParent[i] = -1;
     if (fProcess == kPyJets || fProcess == kPyDirectGamma) {
        TParticle* jet1 = (TParticle *) fParticles->At(6);
        TParticle* jet2 = (TParticle *) fParticles->At(7);
-       if (!CheckTrigger(jet1, jet2)) return 0;
+       if (!CheckTrigger(jet1, jet2)) {
+         delete [] pParent;
+         return 0;
+       }
     }
-    
-    for (i = 0; i<np; i++) {
+
+    if (fTriggerParticle) {
+       Bool_t triggered = kFALSE;
+       for (i = 0; i < np; i++) {
+           TParticle *  iparticle = (TParticle *) fParticles->At(i);
+           kf = CheckPDGCode(iparticle->GetPdgCode());
+           if (kf != fTriggerParticle) continue;
+           if (iparticle->Pt() == 0.) continue;
+           if (TMath::Abs(iparticle->Eta()) > fTriggerEta) continue;
+           triggered = kTRUE;
+           break;
+       }
+       if (!triggered) {
+         delete [] pParent;
+         return 0;
+       }
+    }
+       
+
+    // 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;
+      Bool_t  theQ=kFALSE,theQbar=kFALSE,inYcut=kFALSE;
+      Float_t yQ;  
+      Int_t   pdgQ;
+      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;
+      }
+      if (!theQ || !theQbar || !inYcut) {
+       delete[] pParent;
+       return 0;
+      }
+    }
+
+    //Introducing child cuts in case kPyW, kPyZ, kPyMb, and kPyMbNonDiff
+    if ( (fProcess == kPyW || fProcess == kPyZ || fProcess == kPyMb || fProcess == kPyMbNonDiffr)  
+        && (fCutOnChild == 1) ) {
+      if ( !CheckKinematicsOnChild() ) {
+       delete[] pParent;
+       return 0;
+      }
+    }
+  
+
+    for (i = 0; i < np; i++) {
        Int_t trackIt = 0;
        TParticle *  iparticle = (TParticle *) fParticles->At(i);
        kf = CheckPDGCode(iparticle->GetPdgCode());
@@ -562,21 +798,44 @@ Int_t  AliGenPythia::GenerateMB()
            p[0] = iparticle->Px();
            p[1] = iparticle->Py();
            p[2] = iparticle->Pz();
-           origin[0] = fOrigin[0]+iparticle->Vx()/10.;
-           origin[1] = fOrigin[1]+iparticle->Vy()/10.;
-           origin[2] = fOrigin[2]+iparticle->Vz()/10.;
-           Float_t tof=kconv*iparticle->T();
-           SetTrack(fTrackIt*trackIt, iparent, kf, p, origin, polar,
-                    tof, kPPrimary, nt, 1., ks);
+           p[3] = iparticle->Energy();
+
+           
+           origin[0] = fVertex[0]+iparticle->Vx()/10; // [cm]
+           origin[1] = fVertex[1]+iparticle->Vy()/10; // [cm]
+           origin[2] = fVertex[2]+iparticle->Vz()/10; // [cm]
+           
+           Float_t tof = fEventTime + kconv * iparticle->T();
+
+           PushTrack(fTrackIt*trackIt, iparent, kf, 
+                     p[0], p[1], p[2], p[3], 
+                     origin[0], origin[1], origin[2], tof, 
+                     polar[0], polar[1], polar[2],
+                     kPPrimary, nt, 1., ks);
+           //
+           // 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);
+           
        } // select particle
     } // particle loop 
 
-    if (pParent) delete[] pParent;
+    delete[] pParent;
     
-    printf("\n I've put %i particles on the stack \n",nc);
-    return nc;
+    return 1;
 }
 
 
@@ -584,24 +843,28 @@ void AliGenPythia::FinishRun()
 {
 // Print x-section summary
     fPythia->Pystat(1);
-    fQ  /= fNev;
-    fX1 /= fNev;
-    fX2 /= fNev;    
+
+    if (fNev > 0.) {
+       fQ  /= fNev;
+       fX1 /= fNev;
+       fX2 /= fNev;    
+    }
+    
     printf("\nTotal number of Pyevnt() calls %d\n", fTrialsRun);
     printf("\nMean Q, x1, x2: %f %f %f\n", fQ, fX1, fX2);
-    
-
 }
 
-void AliGenPythia::AdjustWeights()
+void AliGenPythia::AdjustWeights() const
 {
 // Adjust the weights after generation of all events
 //
-    TParticle *part;
-    Int_t ntrack=gAlice->GetNtrack();
-    for (Int_t i=0; i<ntrack; i++) {
-       part= gAlice->Particle(i);
-       part->SetWeight(part->GetWeight()*fKineBias);
+    if (gAlice) {
+       TParticle *part;
+       Int_t ntrack=gAlice->GetMCApp()->GetNtrack();
+       for (Int_t i=0; i<ntrack; i++) {
+           part= gAlice->GetMCApp()->Particle(i);
+           part->SetWeight(part->GetWeight()*fKineBias);
+       }
     }
 }
     
@@ -617,6 +880,14 @@ void AliGenPythia::SetNuclei(Int_t a1, Int_t a2)
 
 void AliGenPythia::MakeHeader()
 {
+//
+// Make header for the simulated event
+// 
+  if (gAlice) {
+    if (gAlice->GetEvNumber()>=fDebugEventFirst &&
+       gAlice->GetEvNumber()<=fDebugEventLast) fPythia->Pylist(2);
+  }
+
 // Builds the event header, to be called after each event
     if (fHeader) delete fHeader;
     fHeader = new AliGenPythiaEventHeader("Pythia");
@@ -628,23 +899,80 @@ void AliGenPythia::MakeHeader()
     ((AliGenPythiaEventHeader*) fHeader)->SetTrials(fTrials);
 //
 // Event Vertex 
-    fHeader->SetPrimaryVertex(fEventVertex);
+    fHeader->SetPrimaryVertex(fVertex);
 //
 // Jets that have triggered
+
     if (fProcess == kPyJets)
     {
        Int_t ntrig, njet;
        Float_t jets[4][10];
        GetJets(njet, ntrig, jets);
+
        
        for (Int_t i = 0; i < ntrig; i++) {
            ((AliGenPythiaEventHeader*) fHeader)->AddJet(jets[0][i], jets[1][i], jets[2][i], 
                                                        jets[3][i]);
        }
     }
-    gAlice->SetGenEventHeader(fHeader);
+//
+// Copy relevant information from external header, if present.
+//
+    Float_t uqJet[4];
+    
+    if (fRL) {
+       AliGenPythiaEventHeader* exHeader = (AliGenPythiaEventHeader*) (fRL->GetHeader()->GenEventHeader());
+       for (Int_t i = 0; i < exHeader->NTriggerJets(); i++)
+       {
+           printf("Adding Jet %d %d \n", i,  exHeader->NTriggerJets());
+           
+           
+           exHeader->TriggerJet(i, uqJet);
+           ((AliGenPythiaEventHeader*) fHeader)->AddUQJet(uqJet[0], uqJet[1], uqJet[2], uqJet[3]);
+       }
+    }
+//
+// Store quenching parameters
+//
+    if (fQuench){
+       Double_t z[4];
+       Double_t xp, yp;
+       if (fQuench == 1) {
+           // Pythia::Quench()
+           fPythia->GetQuenchingParameters(xp, yp, z);
+       } else {
+           // Pyquen
+           Double_t r1 = PARIMP.rb1;
+           Double_t r2 = PARIMP.rb2;
+           Double_t b  = PARIMP.b1;
+           Double_t r   = 0.5 * TMath::Sqrt(2. * (r1 * r1 + r2 * r2) - b * b);
+           Double_t phi = PARIMP.psib1;
+           xp = r * TMath::Cos(phi);
+           yp = r * TMath::Sin(phi);
+           
+       }
+           ((AliGenPythiaEventHeader*) fHeader)->SetXYJet(xp, yp);
+           ((AliGenPythiaEventHeader*) fHeader)->SetZQuench(z);
+       }
+//
+// Store pt^hard 
+    ((AliGenPythiaEventHeader*) fHeader)->SetPtHard(fPythia->GetVINT(47));
+//
+//  Pass header
+//
+    AddHeader(fHeader);
 }
-       
+
+void AliGenPythia::AddHeader(AliGenEventHeader* header)
+{
+    // Add header to container or runloader
+    if (fContainer) {
+       fContainer->AddHeader(header);
+    } else {
+       AliRunLoader::GetRunLoader()->GetHeader()->SetGenEventHeader(header);   
+    }
+}
+
 
 Bool_t AliGenPythia::CheckTrigger(TParticle* jet1, TParticle* jet2)
 {
@@ -693,48 +1021,102 @@ Bool_t AliGenPythia::CheckTrigger(TParticle* jet1, TParticle* jet2)
     }
     return triggered;
 }
+
+
+
+Bool_t AliGenPythia::CheckKinematicsOnChild(){
+//
+//Checking Kinematics on Child (status code 1, particle code ?, kin cuts
+//
+    Bool_t checking = kFALSE;
+    Int_t j, kcode, ks, km;
+    Int_t nPartAcc = 0; //number of particles in the acceptance range
+    Int_t numberOfAcceptedParticles = 1;
+    if (fNumberOfAcceptedParticles != 0) { numberOfAcceptedParticles = fNumberOfAcceptedParticles; }
+    Int_t npart = fParticles->GetEntriesFast();
+    
+    for (j = 0; j<npart; j++) {
+       TParticle *  jparticle = (TParticle *) fParticles->At(j);
+       kcode = TMath::Abs( CheckPDGCode(jparticle->GetPdgCode()) );
+       ks = jparticle->GetStatusCode();
+       km = jparticle->GetFirstMother(); 
+       
+       if( (ks == 1)  &&  (kcode == fPdgCodeParticleforAcceptanceCut)  &&  (KinematicSelection(jparticle,1)) ){
+           nPartAcc++;
+       }
+       if( numberOfAcceptedParticles <= nPartAcc){
+         checking = kTRUE;
+         break;
+       }
+    }
+
+    return checking;
+}
+
          
 AliGenPythia& AliGenPythia::operator=(const  AliGenPythia& rhs)
 {
 // Assignment operator
+    rhs.Copy(*this);
     return *this;
 }
 
-void  AliGenPythia::LoadEvent()
+void  AliGenPythia::LoadEvent(AliStack* stack, Int_t flag, Int_t reHadr)
 {
 //
 // Load event into Pythia Common Block
 //
-
-    Int_t npart = (Int_t) (gAlice->TreeK())->GetEntries(); 
-   (fPythia->GetPyjets())->N = npart;
 
+    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 = gAlice->Particle(part);
-       Int_t kf     = MPart->GetPdgCode();
-       Int_t ks     = MPart->GetStatusCode();
-       Float_t px = MPart->Px();
-       Float_t py = MPart->Py();
-       Float_t pz = MPart->Pz();
-       Float_t e  = MPart->Energy();
-       Float_t p  = TMath::Sqrt(px * px + py * py + pz * pz);
-       Float_t m  = TMath::Sqrt(e * e - p * p);
+       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 (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] = px;
-       (fPythia->GetPyjets())->P[1][part] = py;
-       (fPythia->GetPyjets())->P[2][part] = pz;
-       (fPythia->GetPyjets())->P[3][part] = e;
-       (fPythia->GetPyjets())->P[4][part] = m;
+       (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] = kf;
-       (fPythia->GetPyjets())->K[0][part] = ks;
+       (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::RecJetsUA1(Float_t eCellMin, Float_t eCellSeed, Float_t eMin, Float_t rMax, 
-                             Int_t& njets, Float_t jets [4][50])
+
+void AliGenPythia::RecJetsUA1(Int_t& njets, Float_t jets [4][50])
 {
 //
 //  Calls the Pythia jet finding algorithm to find jets in the current event
@@ -798,11 +1180,10 @@ void  AliGenPythia::GetJets(Int_t& nJets, Int_t& nJetsTrig, Float_t jets[4][10])
        Float_t pz    = (fPythia->GetPyjets())->P[2][n+i];
        Float_t e     = (fPythia->GetPyjets())->P[3][n+i];
        Float_t pt    = TMath::Sqrt(px * px + py * py);
-       Float_t phi   = TMath::ATan2(py,px);
+       Float_t phi   = TMath::Pi() + TMath::ATan2(-py, -px);  
        Float_t theta = TMath::ATan2(pt,pz);
        Float_t et    = e * TMath::Sin(theta);
        Float_t eta   = -TMath::Log(TMath::Tan(theta / 2.));
-
        if (
            eta > fEtaMinJet && eta < fEtaMaxJet && 
            phi > fPhiMinJet && phi < fPhiMaxJet &&
@@ -814,13 +1195,24 @@ void  AliGenPythia::GetJets(Int_t& nJets, Int_t& nJetsTrig, Float_t jets[4][10])
            jets[2][nJetsTrig] = pz;
            jets[3][nJetsTrig] = e;
            nJetsTrig++;
-           
+//         printf("\n........-Jet #%d: %10.3f %10.3f %10.3f %10.3f \n", i, pt, et, eta, phi * kRaddeg);
        } else {
 //         printf("\n........-Jet #%d: %10.3f %10.3f %10.3f %10.3f \n", i, pt, et, eta, phi * kRaddeg);
        }
     }
 }
 
+void AliGenPythia::GetSubEventTime()
+{
+  // Calculates time of the next subevent
+  fEventTime = 0.;
+  if (fEventsTime) {
+    TArrayF &array = *fEventsTime;
+    fEventTime = array[fCurSubEvent++];
+  }
+  //  printf(" Event time: %d %f %p",fCurSubEvent,fEventTime,fEventsTime);
+  return;
+}
 
 #ifdef never
 void AliGenPythia::Streamer(TBuffer &R__b)
@@ -863,3 +1255,5 @@ void AliGenPythia::Streamer(TBuffer &R__b)
 }
 #endif
 
+
+