Index: branches/v3.1/runglauber_v3.1.C
===================================================================
--- branches/v3.1/runglauber_v3.1.C	(revision 177)
+++ branches/v3.1/runglauber_v3.1.C	(revision 178)
@@ -1,2075 +1,2075 @@
 /*
  $Id: runglauber.C 173 2018-06-07 19:47:47Z loizides $
  -------------------------------------------------------------------------------------
  Latest documentation: https://arxiv.org/abs/1710.07098
  -------------------------------------------------------------------------------------
  To run the code, you need to have the ROOT (http://root.cern.ch/drupal/)
  environment. On the root prompt, then enter
  root [0] gSystem->Load("libMathMore")
  root [1] .L runglauber_X.Y.C+
  (where X.Y denotes the version number).
  If you do not have libMathMore comment out "#define HAVE_MATHMORE" below.
  See the documentation for more information.
  -------------------------------------------------------------------------------------
  v3.1:
   Fixes related to spherical nuclei, as well as consistent set of reweighted profiles 
   for Cu, Au and Xe, see https://arxiv.org/abs/1710.07098v2
  -------------------------------------------------------------------------------------
  v3.0:
   Major update to include separate profile for protons and neutrons, placement of nucleon 
   dof on lattice, as well as reweighted profiles for recentering, 
   see https://arxiv.org/abs/1710.07098v1
  -------------------------------------------------------------------------------------
  v2.6:
   Includes runAndCalcDens macro, as well as definition for Al, and fixes beta4 for Si2,
   see https://arxiv.org/abs/1408.2549v8
  -------------------------------------------------------------------------------------
  v2.5:
   Include core/corona determination in Npart, and if requested for area from mc and eccentricity,
   as well as various Xe parameterizations including deformation,
   see https://arxiv.org/abs/1408.2549v7
  -------------------------------------------------------------------------------------
  v2.4: 
   Minor update to include Xenon and fix of the TGlauberMC::Draw function, 
   see https://arxiv.org/abs/1408.2549v4
  -------------------------------------------------------------------------------------
  v2.3: 
   Small bugfixes, see https://arxiv.org/abs/1408.2549v3
  -------------------------------------------------------------------------------------
  v2.2:
   Minor update to provide higher harmonic eccentricities up to n=5, and the average
   nucleon--nucleon impact parameter (bNN) in tree output. 
  -------------------------------------------------------------------------------------
  v2.1: 
   Minor update to include more proton pdfs, see https://arxiv.org/abs/1408.2549v2
  -------------------------------------------------------------------------------------
  v2.0: 
   First major update with inclusion of Tritium, Helium-3, and Uranium, as well as the 
   treatment of deformed nuclei and Glauber-Gribov fluctuations of the proton in p+A 
   collisions, see https://arxiv.org/abs/1408.2549v1
  -------------------------------------------------------------------------------------
  v1.1: 
   First public release of the PHOBOS MC Glauber, see https://arxiv.org/abs/0805.4411
  -------------------------------------------------------------------------------------
 
  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 <http://www.gnu.org/licenses/>
 */
 
 #define HAVE_MATHMORE
 
 #if !defined(__CINT__) || defined(__MAKECINT__)
 #include <Riostream.h>
 #include <TBits.h>
 #include <TCanvas.h>
 #include <TEllipse.h>
 #include <TF1.h>
 #include <TF2.h>
 #include <TFile.h>
 #include <TH2.h>
 #include <TLine.h>
 #include <TMath.h>
 #include <TNamed.h>
 #include <TNtuple.h>
 #include <TObjArray.h>
 #include <TRandom.h>
 #include <TRotation.h>
 #include <TString.h>
 #include <TSystem.h>
 #include <TVector3.h>
 #ifdef HAVE_MATHMORE
  #include <Math/SpecFuncMathMore.h>
 #endif
 using namespace std;
 #endif
 
 #ifndef _runglauber_
 #if !defined(__CINT__) || defined(__MAKECINT__)
 #define _runglauber_ 3
 #endif
 
 //---------------------------------------------------------------------------------
 TF1 *getNNProf(Double_t snn=67.6, Double_t omega=0.4, Double_t G=1);
 
 //---------------------------------------------------------------------------------
 void runAndSaveNtuple(const Int_t n,
                       const char *sysA        = "Pb",
                       const char *sysB        = "Pb",
                       const Double_t signn    = 67.6,
                       const Double_t sigwidth = -1,
                       const Double_t mind     = 0.4,
 		      const Double_t omega    = -1,
                       const Double_t noded    = -1,
                       const char *fname       = 0);
 
 //---------------------------------------------------------------------------------
 void runAndSaveNucleons(const Int_t n,                    
                         const char *sysA        = "Pb",           
                         const char *sysB        = "Pb",           
                         const Double_t signn    = 67.6,           
                         const Double_t sigwidth = -1,
                         const Double_t mind     = 0.4,
                         const Bool_t verbose    = 0,
                         const char *fname       = 0);
 
 //---------------------------------------------------------------------------------
 void runAndSmearNtuple(const Int_t n,
                        const Double_t sigs  = 0.4,
                        const char *sysA     = "p",
                        const char *sysB     = "Pb",
                        const Double_t signn = 67.6,
                        const Double_t mind  = 0.4,
                        const char *fname    = 0);
 
 //---------------------------------------------------------------------------------
 void runAndCalcDens(const Int_t n,
 		    const Double_t alpha = 0.1,
 		    const char *sysA     = "Pb",
 		    const char *sysB     = "Pb",
 		    const Double_t signn = 67.6,
 		    const Double_t mind  = 0.4,
 		    const char *fname    = "glau_dens_hists.root");
 
 //---------------------------------------------------------------------------------
 class TGlauNucleon : public TObject
 {
   protected:
     Double32_t fX;            //Position of nucleon
     Double32_t fY;            //Position of nucleon
     Double32_t fZ;            //Position of nucleon
     Int_t      fType;         //0 = neutron, 1 = proton
     Bool_t     fInNucleusA;   //=1 from nucleus A, =0 from nucleus B
     Int_t      fNColl;        //Number of binary collisions
     Double32_t fEn;           //Energy
   public:
     TGlauNucleon() : fX(0), fY(0), fZ(0), fInNucleusA(0), fNColl(0), fEn(0) {}
     virtual   ~TGlauNucleon() {}
     void       Collide()                                  {++fNColl;}
     Double_t   Get2CWeight(Double_t x) const              {return 2.*(0.5*(1-x)+0.5*x*fNColl);}
     Double_t   GetEnergy()             const              {return fEn;}
     Int_t      GetNColl()              const              {return fNColl;}
     Int_t      GetType()               const              {return fType;}
     Double_t   GetX()                  const              {return fX;}
     Double_t   GetY()                  const              {return fY;}
     Double_t   GetZ()                  const              {return fZ;}
     Bool_t     IsNeutron()             const              {return (fType==0);}
     Bool_t     IsInNucleusA()          const              {return fInNucleusA;}
     Bool_t     IsInNucleusB()          const              {return !fInNucleusA;}
     Bool_t     IsProton()              const              {return (fType==1);}
     Bool_t     IsSpectator()           const              {return !fNColl;}
     Bool_t     IsWounded()             const              {return fNColl>0;}
     void       Reset()                                    {fNColl=0;}
     void       RotateXYZ(Double_t phi, Double_t theta);
     void       RotateXYZ_3D(Double_t psiX, Double_t psiY, Double_t psiZ);
     void       SetEnergy(Double_t en)                     {fEn = en;}
     void       SetInNucleusA()                            {fInNucleusA=1;}
     void       SetInNucleusB()                            {fInNucleusA=0;}
     void       SetNColl(Int_t nc)                         {fNColl = nc;}
     void       SetType(Bool_t b)                          {fType = b;}
     void       SetXYZ(Double_t x, Double_t y, Double_t z) {fX=x; fY=y; fZ=z;}
     ClassDef(TGlauNucleon,4) // TGlauNucleon class
 };
 
 //---------------------------------------------------------------------------------
 ClassImp(TGlauNucleon)
   //---------------------------------------------------------------------------------
 void TGlauNucleon::RotateXYZ(Double_t phi, Double_t theta)
 {
   TVector3 v(fX,fY,fZ);
   TVector3 vr;
   vr.SetMagThetaPhi(1,theta,phi);
   v.RotateUz(vr);
   fX = v.X();
   fY = v.Y();
   fZ = v.Z();
 }
 
 void TGlauNucleon::RotateXYZ_3D(Double_t psiX, Double_t psiY, Double_t psiZ)
 {
   TVector3 v(fX,fY,fZ);
   v.RotateX(psiX);
   v.RotateY(psiY);
   v.RotateZ(psiZ);
   fX = v.X();
   fY = v.Y();
   fZ = v.Z();
 }
 
 //---------------------------------------------------------------------------------
 class TGlauNucleus : public TNamed
 {
   private:
     Int_t      fN;                   //Number of nucleons
     Int_t      fZ;                   //Number of protons
     Double_t   fR;                   //Parameters of function
     Double_t   fA;                   //Parameters of function (fA+fZ=fN)
     Double_t   fW;                   //Parameters of function
     Double_t   fR2;                  //Parameters of function (for p and n separately)
     Double_t   fA2;                  //Parameters of function (for p and n separately)
     Double_t   fW2;                  //Parameters of function (for p and n separately)
     Double_t   fBeta2;               //Beta2 (deformed nuclei) 
     Double_t   fBeta4;               //Beta4 (deformed nuclei) 
     Double_t   fMinDist;             //Minimum separation distance
     Double_t   fNodeDist;            //Average node distance (set to <=0 if you do not want the "crystal lattice")
     Double_t   fSmearing;            //Node smearing (relevant if fNodeDist>0)
     Int_t      fRecenter;            //=1 by default (0=no recentering, 1=recenter all, 2=recenter displacing only one nucleon, 3=recenter by rotation)
     Int_t      fLattice;             //=0 use HCP by default (1=PCS, 2=BCC, 3=FCC)
     Double_t   fSmax;                //Maximum magnitude of cms shift tolerated (99, ie all by default) 
     Int_t      fF;                   //Type of radial distribution
     Int_t      fTrials;              //Store trials needed to complete nucleus
     Int_t      fNonSmeared;          //Store number of non-smeared-node nucleons
     TF1*       fFunc1;               //!Probability density function rho(r)
     TF1*       fFunc2;               //!Probability density function rho(r) -> if set 1 is for p, 2 is for n
     TF2*       fFunc3;               //!Probability density function rho(r,theta) for deformed nuclei
     TObjArray* fNucleons;            //!Array of nucleons
     Double_t   fPhiRot;              //!Angle phi for nucleus
     Double_t   fThetaRot;            //!Angle theta for nucleus
     Double_t   fXRot;                //!Angle around X axis for nucleus
     Double_t   fYRot;                //!Angle around Y axis for nucleus
     Double_t   fZRot;                //!Angle around Z axis for nucleus
     Double_t   fHe3Arr[6000][3][3];  //!Array of events, 3 nucleons, 3 coordinates
     Int_t      fHe3Counter;          //!Event counter
     TBits     *fIsUsed;              //!Bits for lattice use  
     Double_t   fMaxR;                //!maximum radius (15fm)
     void       Lookup(const char* name);
     Bool_t     TestMinDist(Int_t n, Double_t x, Double_t y, Double_t z) const;
 
   public:
     TGlauNucleus(const char* iname="Pb", Int_t iN=0, Double_t iR=0, Double_t ia=0, Double_t iw=0, TF1* ifunc=0);
     virtual ~TGlauNucleus();
     using      TObject::Draw;
     void       Draw(Double_t xs, Int_t colp, Int_t cols);
     Double_t   GetA()             const {return fA;}
     TF1*       GetFunc1()         const {return GetFuncP();}
     TF1*       GetFunc2()         const {return GetFuncN();}
     TF2*       GetFunc3()         const {return GetFuncDef();}
     TF1*       GetFuncP()         const {return fFunc1;}
     TF1*       GetFuncN()         const {return fFunc2;}
     TF2*       GetFuncDef()       const {return fFunc3;}
     Double_t   GetMinDist()       const {return fMinDist;}
     Int_t      GetN()             const {return fN;}
     Double_t   GetNodeDist()      const {return fNodeDist;}
     TObjArray *GetNucleons()      const {return fNucleons;}
     Int_t      GetRecenter()      const {return fRecenter;}
     Double_t   GetR()             const {return fR;}
     Double_t   GetPhiRot()        const {return fPhiRot;}
     Double_t   GetThetaRot()      const {return fThetaRot;}
     Int_t      GetTrials()        const {return fTrials;}
     Int_t      GetNonSmeared()    const {return fNonSmeared;}
     Double_t   GetShiftMax()      const {return fSmax;}
     Double_t   GetW()             const {return fW;}
     Double_t   GetXRot()          const {return fXRot;}
     Double_t   GetYRot()          const {return fYRot;}
     Double_t   GetZRot()          const {return fZRot;}
     void       SetA(Double_t ia, Double_t ia2=-1);
     void       SetBeta(Double_t b2, Double_t b4); 
     void       SetLattice(Int_t i)               {fLattice=i;}
     void       SetMinDist(Double_t min)          {fMinDist=min;}
     void       SetN(Int_t in)                    {fN=in;}
     void       SetNodeDist(Double_t nd)          {fNodeDist=nd;}
     void       SetR(Double_t ir, Double_t ir2=-1);
     void       SetRecenter(Int_t b)              {fRecenter=b;}
     void       SetShiftMax(Double_t s)           {fSmax=s;}
     void       SetSmearing(Double_t s)           {fSmearing=s;}
     void       SetW(Double_t iw);
     TVector3  &ThrowNucleons(Double_t xshift=0.);
     ClassDef(TGlauNucleus,6) // TGlauNucleus class
 };
 
 //---------------------------------------------------------------------------------
 class TGlauberMC : public TNamed
 {
   public:
     class Event {
       public:
         Float_t Npart;       //Number of wounded (participating) nucleons in current event
         Float_t Ncoll;       //Number of binary collisions in current event
         Float_t Nhard;       //Number of hard collisions in current event (based on fHardFrac)
         Float_t B;           //[0,0,16] Impact parameter (b)
         Float_t BNN;         //[0,0,16] Average NN impact parameter
         Float_t Ncollpp;     //Ncoll pp
         Float_t Ncollpn;     //Ncoll pn
         Float_t Ncollnn;     //Ncoll nn
         Float_t VarX;        //[0,0,16] Variance of x of wounded nucleons
         Float_t VarY;        //[0,0,16] Variance of y of wounded nucleons
         Float_t VarXY;       //[0,0,16] Covariance of x and y of wounded nucleons
         Float_t NpartA;      //Number of wounded (participating) nucleons in Nucleus A
         Float_t NpartB;      //Number of wounded (participating) nucleons in Nucleus B
         Float_t Npart0;      //Number of singly-wounded (participating) nucleons
         Float_t AreaW;       //[0,0,16] area defined by width of participants
         Float_t Psi1;        //[0,0,16] psi1
         Float_t Ecc1;        //[0,0,16] eps1
         Float_t Psi2;        //[0,0,16] psi2
         Float_t Ecc2;        //[0,0,16] eps2
         Float_t Psi3;        //[0,0,16] psi3
         Float_t Ecc3;        //[0,0,16] eps3
         Float_t Psi4;        //[0,0,16] psi4
         Float_t Ecc4;        //[0,0,16] eps4
         Float_t Psi5;        //[0,0,16] psi5
         Float_t Ecc5;        //[0,0,16] eps5
         Float_t AreaA;       //[0,0,16] area defined by "and" of participants
         Float_t AreaO;       //[0,0,16] area defined by "or" of participants
         Float_t X0;          //[0,0,16] production point in x
         Float_t Y0;          //[0,0,16] production point in y
         Float_t Phi0;        //[0,0,16] direction in phi
         Float_t Length;      //[0,0,16] length in phi0
         Float_t MeanX;       //[0,0,16] <x> of wounded nucleons
         Float_t MeanY;       //[0,0,16] <y> of wounded nucleons
         Float_t MeanX2;      //[0,0,16] <x^2> of wounded nucleons
         Float_t MeanY2;      //[0,0,16] <y^2> of wounded nucleons
         Float_t MeanXY;      //[0,0,16] <xy> of wounded nucleons
         Float_t MeanXSystem; //[0,0,16] <x> of all nucleons
         Float_t MeanYSystem; //[0,0,16] <y> of all nucleons  
         Float_t MeanXA;      //[0,0,16] <x> of nucleons in nucleus A
         Float_t MeanYA;      //[0,0,16] <y> of nucleons in nucleus A
         Float_t MeanXB;      //[0,0,16] <x> of nucleons in nucleus B
         Float_t MeanYB;      //[0,0,16] <y> of nucleons in nucleus B
         Float_t PhiA;        //[0,0,16] phi angle nucleus A
         Float_t ThetaA;      //[0,0,16] theta angle nucleus B
         Float_t PhiB;        //[0,0,16] phi angle nucleus B
         Float_t ThetaB;      //[0,0,16] theta angle nucleus B
         void    Reset()      {Npart=0;Ncoll=0;Nhard=0;B=0;BNN=0;Ncollpp=0;Ncollpn=0;Ncollnn=0;VarX=0;VarY=0;VarXY=0;NpartA=0;NpartB=0;Npart0=0;AreaW=0;
                               Psi1=0;Ecc1=0;Psi2=0;Ecc2=0;Psi3=0;Ecc3=0;Psi4=0;Ecc4=0;Psi5=0;Ecc5=0;
                               AreaA=0;AreaO=0;X0=0;Y0=0;Phi0=0;Length=0;
                               MeanX=0;MeanY=0;MeanX2=0;MeanY2=0;MeanXY=0;MeanXSystem=0;MeanYSystem=0;MeanXA=0;MeanYA=0;MeanXB=0;MeanYB=0;
                               PhiA=0;ThetaA=0;PhiB=0;ThetaB=0;} // order must match that given in vars below
         ClassDef(TGlauberMC::Event, 1)
     };
 
   protected:
     TGlauNucleus  fANucleus;       //Nucleus A
     TGlauNucleus  fBNucleus;       //Nucleus B
     Double_t      fXSect;          //Nucleon-nucleon cross section
     Double_t      fXSectOmega;     //StdDev of Nucleon-nucleon cross section
     Double_t      fXSectLambda;    //Jacobian from tot to inelastic (Strikman)
     Double_t      fXSectEvent;     //Event value of Nucleon-nucleon cross section
     TObjArray*    fNucleonsA;      //Array of nucleons in nucleus A
     TObjArray*    fNucleonsB;      //Array of nucleons in nucleus B
     TObjArray*    fNucleons;       //Array which joins Nucleus A & B
     Int_t         fAN;             //Number of nucleons in nucleus A
     Int_t         fBN;             //Number of nucleons in nucleus B
     TNtuple*      fNt;             //Ntuple for results (created, but not deleted)
     Int_t         fEvents;         //Number of events with at least one collision
     Int_t         fTotalEvents;    //All events within selected impact parameter range
     Double_t      fBmin;           //Minimum impact parameter to be generated
     Double_t      fBmax;           //Maximum impact parameter to be generated
     Double_t      fHardFrac;       //Fraction of cross section used for Nhard (def=0.65)
     Int_t         fDetail;         //Detail to store (99=all by default)
     Bool_t        fCalcArea;       //If true calculate overlap area via grid (slow, off by default)
     Bool_t        fCalcLength;     //If true calculate path length (slow, off by default)
     Bool_t        fDoCore;         //If true calculate area and eccentricy only for core participants (off by default)
     Int_t         fMaxNpartFound;  //Largest value of Npart obtained
     Double_t      fPsiN[10];       //Psi N
     Double_t      fEccN[10];       //Ecc N
     Double_t      f2Cx;            //Two-component x
     TF1          *fPTot;           //Cross section distribution
     TF1          *fNNProf;         //NN profile (hard-sphere == 0 by default)
     Event         fEv;             //Glauber event (results of calculation stored in tree)
     Bool_t        fBC[999][999];   //Array to record binary collision
     Bool_t        CalcResults(Double_t bgen);
     Bool_t        CalcEvent(Double_t bgen);
 
   public:
     TGlauberMC(const char* NA = "Pb", const char* NB = "Pb", Double_t xsect = 42, Double_t xsectsigma=0);
   virtual            ~TGlauberMC() {delete fNt; fNt=0;}
 
     Double_t            CalcDens(TF1 &prof, Double_t xval, Double_t yval) const;
     void                Draw(Option_t* option="");
     Double_t            GetB()                 const {return fEv.B;}
     Double_t            GetBNN()               const {return fEv.BNN;}
     Double_t            GetBmax()              const {return fBmax;}
     Double_t            GetBmin()              const {return fBmin;}
     Double_t            GetEcc(Int_t i=2)      const {return fEccN[i];}
     Double_t            GetHardFrac()          const {return fHardFrac;}
     Double_t            GetMeanX()             const {return fEv.MeanX;}
     Double_t            GetMeanXParts()        const {return fEv.MeanX;}
     Double_t            GetMeanXSystem()       const {return fEv.MeanXSystem;}
     Double_t            GetMeanY()             const {return fEv.MeanY;}
     Double_t            GetMeanYParts()        const {return fEv.MeanY;}
     Double_t            GetMeanYSystem()       const {return fEv.MeanYSystem;}
     Double_t            GetPsi(Int_t i=2)      const {return fPsiN[i];}
     Double_t            GetSx2()               const {return fEv.VarX;}    
     Double_t            GetSxy()               const {return fEv.VarXY;}    
     Double_t            GetSy2()               const {return fEv.VarY;}    
     Double_t            GetTotXSect()          const;
     Double_t            GetTotXSectErr()       const;
     Double_t            GetXSectEvent()        const {return fXSectEvent;}
     Int_t               GetNcoll()             const {return fEv.Ncoll;}
     Int_t               GetNcollnn()           const {return fEv.Ncollnn;}
     Int_t               GetNcollpn()           const {return fEv.Ncollpn;}
     Int_t               GetNcollpp()           const {return fEv.Ncollpp;}
     Int_t               GetNpart()             const {return fEv.Npart;}
     Int_t               GetNpart0()            const {return fEv.Npart0;}
     Int_t               GetNpartA()            const {return fEv.NpartA;}
     Int_t               GetNpartB()            const {return fEv.NpartB;}
     Int_t               GetNpartFound()        const {return fMaxNpartFound;}
     TF1*                GetXSectDist()         const {return fPTot;}
     TGlauNucleus*       GetNucleusA()                {return &fANucleus;}
     TGlauNucleus*       GetNucleusB()                {return &fBNucleus;}
     TNtuple*            GetNtuple()            const {return fNt;}
     TObjArray          *GetNucleons();
     const Event        &GetEvent()             const {return fEv;}
     const Event        *GetEvent()                   {return &fEv;}
     const TGlauNucleus* GetNucleusA()          const {return &fANucleus;}
     const TGlauNucleus* GetNucleusB()          const {return &fBNucleus;}
     Bool_t              IsBC(Int_t i, Int_t j) const {return fBC[i][j];}
     Bool_t              NextEvent(Double_t bgen=-1);
     void                Reset()                      {delete fNt; fNt=0; }
     Bool_t              ReadNextEvent(Bool_t calc=1, const char *fname=0);       
     void                Run(Int_t nevents,Double_t b=-1);
     void                Set2Cx(Double_t x)           {f2Cx = x;}
     void                SetBmax(Double_t bmax)       {fBmax = bmax;}
     void                SetBmin(Double_t bmin)       {fBmin = bmin;}
     void                SetCalcArea(Bool_t b)        {fCalcArea = b;}
     void                SetCalcCore(Bool_t b)        {fDoCore = b;}
     void                SetCalcLength(Bool_t b)      {fCalcLength = b;}
     void                SetDetail(Int_t d)           {fDetail = d;}
     void                SetHardFrac(Double_t f)      {fHardFrac=f;}
     void                SetLattice(Int_t i)          {fANucleus.SetLattice(i); fBNucleus.SetLattice(i);}
     void                SetMinDistance(Double_t d)   {fANucleus.SetMinDist(d); fBNucleus.SetMinDist(d);}
     void                SetNNProf(TF1 *f1)           {fNNProf = f1;}
     void                SetNodeDistance(Double_t d)  {fANucleus.SetNodeDist(d); fBNucleus.SetNodeDist(d);}
     void                SetRecenter(Int_t b)         {fANucleus.SetRecenter(b); fBNucleus.SetRecenter(b);}
     void                SetShiftMax(Double_t s)      {fANucleus.SetShiftMax(s); fBNucleus.SetShiftMax(s);}
     void                SetSmearing(Double_t s)      {fANucleus.SetSmearing(s); fBNucleus.SetSmearing(s);}
     const char         *Str()                  const {return Form("gmc-%s%s-snn%.1f-md%.1f-nd%.1f-rc%d-smax%.1f",fANucleus.GetName(),fBNucleus.GetName(),fXSect,fBNucleus.GetMinDist(),fBNucleus.GetNodeDist(),fBNucleus.GetRecenter(),fBNucleus.GetShiftMax());}
     static void         PrintVersion()               {cout << "TGlauberMC " << Version() << endl;}
     static const char  *Version()                    {return "v3.1a";}
 
     ClassDef(TGlauberMC,6) // TGlauberMC class
 };
 
 //---------------------------------------------------------------------------------
 TF1 *getNNProf(Double_t snn, Double_t omega, Double_t G) 
 { // NN collisoin profile from https://arxiv.org/abs/1307.0636
   if ((omega<0) || (omega>1))
     return 0;
   Double_t R2 = snn/10./TMath::Pi();
   TF1 *nnprof = new TF1("nnprofgamma","[2]*(1-TMath::Gamma([0],[1]*x^2))",0,3);
   nnprof->SetParameters(1./omega,G/omega/R2,G);
   return nnprof;
 }
 
 //---------------------------------------------------------------------------------
 void runAndSaveNtuple(const Int_t n,
                       const char *sysA,
                       const char *sysB,
                       const Double_t signn,
                       const Double_t sigwidth,
                       const Double_t mind,
 		      const Double_t omega,
                       const Double_t noded,
                       const char *fname)
 {
   TGlauberMC *mcg=new TGlauberMC(sysA,sysB,signn,sigwidth);
   mcg->SetMinDistance(mind);
   mcg->SetNodeDistance(noded);
   mcg->SetCalcLength(0);
   mcg->SetCalcArea(0);
   mcg->SetCalcCore(0);
   mcg->SetDetail(99);
   TString om;
   if ((omega>=0) && (omega<=1)) {
     TF1 *f1 = getNNProf(signn, omega);
     mcg->SetNNProf(f1);
     om=Form("-om%.1f",omega);
   }
   TString name;
   if (fname) 
     name = fname; 
   else {
     TString nd;
     if (noded>0) 
       nd=Form("-nd%.1f",noded);
     name = Form("%s%s%s.root",mcg->Str(),om.Data(),nd.Data());
   }
   mcg->Run(n);
   TFile out(name,"recreate",name,9);
   TNtuple  *nt=mcg->GetNtuple();
   nt->Write();
   out.Close();
 }
 
 //---------------------------------------------------------------------------------
 void runAndSaveNucleons(const Int_t n,                    
                         const char *sysA,           
                         const char *sysB,           
                         const Double_t signn,
                         const Double_t sigwidth,
                         const Double_t mind,
                         const Bool_t verbose,
                         const char *fname)
 {
   TGlauberMC *mcg=new TGlauberMC(sysA,sysB,signn,sigwidth);
   mcg->SetMinDistance(mind);
   TFile *out=0;
   if (fname) 
     out=new TFile(fname,"recreate",fname,9);
 
   for (Int_t ievent=0; ievent<n; ++ievent) {
     //get an event with at least one collision
     mcg->Run(1);
     if (ievent%100==0)
       cout << "\r" << 100.*ievent/n << "% done" << flush;
 
     //access, save and (if wanted) print out nucleons
     TObjArray* nucleons=mcg->GetNucleons();
     if (!nucleons) 
       continue;
     if (out)
       nucleons->Write(Form("nucleonarray%d",ievent),TObject::kSingleKey);
 
     if (verbose) {
       cout<<endl<<endl<<"EVENT NO: "<<ievent<<endl;
       cout<<"B = "<<mcg->GetB()<<"  Npart = "<<mcg->GetNpart()<<endl<<endl;
       printf("Nucleus\t X\t Y\t Z\tNcoll\n");
       Int_t nNucls=nucleons->GetEntries();
       for (Int_t iNucl=0; iNucl<nNucls; ++iNucl) {
         TGlauNucleon *nucl=(TGlauNucleon *)nucleons->At(iNucl);
         Char_t nucleus='A';
         if (nucl->IsInNucleusB()) 
 	  nucleus='B';
         Double_t x=nucl->GetX();
         Double_t y=nucl->GetY();
         Double_t z=nucl->GetZ();
         Int_t ncoll=nucl->GetNColl();
         printf("   %c\t%2.2f\t%2.2f\t%2.2f\t%3d\n",nucleus,x,y,z,ncoll);
       }
     }
   }
   cout << endl << "Done!" << endl;
   if (out) {
     TNtuple *nt = mcg->GetNtuple();
     nt->Write();
     if (verbose)
       out->ls();
     delete out;
   }
 }
 
 //---------------------------------------------------------------------------------
 void runAndSmearNtuple(const Int_t n,
                        const Double_t sigs,
                        const char *sysA,
                        const char *sysB,
                        const Double_t signn,
                        const Double_t mind,
                        const char *fname)
 {
   // Run Glauber and store ntuple with smeared eccentricities in file.
 
   TGlauberMC *mcg = new TGlauberMC(sysA,sysB,signn);
   mcg->SetMinDistance(mind);
   TFile *out = TFile::Open(fname,"recreate",fname,9);
   if (!out)
     return;
   TNtuple *nt = new TNtuple("nt","nt",
       "Npart:Ncoll:B:Psi1P:Ecc1P:Psi2P:Ecc2P:Psi3P:Ecc3P:Psi4P:Ecc4P:Psi5P:Ecc5P:Psi1G:Ecc1G:Psi2G:Ecc2G:Psi3G:Ecc3G:Psi4G:Ecc4G:Psi5G:Ecc5G:Sx2P:Sy2P:Sx2G:Sy2G");
   nt->SetDirectory(out);
 
   const Int_t NSAMP = 100;
   TF1 *rad = new TF1("rad","x*TMath::Exp(-x*x/(2.*[0]*[0]))",0.0,3*sigs);
   rad->SetParameter(0,sigs);
 
   for (Int_t ievent=0; ievent<n; ++ievent) {
     while (!mcg->NextEvent()) {}
 
     const TGlauNucleus *nucA   = mcg->GetNucleusA();
     const TObjArray *nucleonsA = nucA->GetNucleons();
     const Int_t AN             = nucA->GetN();
     const TGlauNucleus *nucB   = mcg-> GetNucleusB();
     const TObjArray *nucleonsB = nucB->GetNucleons();
     const Int_t BN             = nucB->GetN();
     Double_t sinphi[10] = {0};
     Double_t cosphi[10] = {0};
     Double_t rn[10]     = {0};
     Double_t ecc[10]    = {0};
     Double_t psi[10]    = {0};
     Double_t sx2g       = 0;
     Double_t sy2g       = 0;
 
     for (Int_t s=0; s<NSAMP; ++s) {
       Int_t ni = 0;
       Double_t xvals[1000] = {0};
       Double_t yvals[1000] = {0};
       for (Int_t i = 0; i<AN; ++i) {
         TGlauNucleon *nucleonA=(TGlauNucleon*)(nucleonsA->At(i));
         if (!nucleonA->IsWounded())
           continue;
         Double_t sr = rad->GetRandom();
         Double_t sp = gRandom->Uniform(-TMath::Pi(), +TMath::Pi());
         xvals[ni]   = nucleonA->GetX() + sr*TMath::Cos(sp);
         yvals[ni]   = nucleonA->GetY() + sr*TMath::Sin(sp);
         ++ni;
       }
       for (Int_t i = 0; i<BN; ++i) {
         TGlauNucleon *nucleonB=(TGlauNucleon*)(nucleonsB->At(i));
         if (!nucleonB->IsWounded())
           continue;
         Double_t sr = rad->GetRandom();
         Double_t sp = gRandom->Uniform(-TMath::Pi(), +TMath::Pi());
         xvals[ni]   = nucleonB->GetX() + sr*TMath::Cos(sp);
         yvals[ni]   = nucleonB->GetY() + sr*TMath::Sin(sp);
         ++ni;
       }
 
       Double_t MeanX  = 0;
       Double_t MeanY  = 0;
       Double_t MeanX2 = 0;
       Double_t MeanY2 = 0;
       for (Int_t i = 0; i<ni; ++i) {
         MeanX  += xvals[i];
         MeanY  += yvals[i];
         MeanX2 += xvals[i]*xvals[i];
         MeanY2 += yvals[i]*yvals[i];
       }
       MeanX  /= ni;
       MeanY  /= ni;
       MeanX2 /= ni;
       MeanY2 /= ni;
       sx2g        += MeanX2-MeanX*MeanX;
       sy2g        += MeanY2-MeanY*MeanY;
 
       for (Int_t j = 1; j<9; ++j) {
         for (Int_t i = 0; i<ni; ++i) {
           Double_t x   = xvals[i] - MeanX;
           Double_t y   = yvals[i] - MeanY;
           Double_t r   = TMath::Sqrt(x*x+y*y);
           Double_t phi = TMath::ATan2(y,x);
           Double_t w = j;
           if (j==1)
             w = 3; // use r^3 weighting for Ecc1/Psi1
           cosphi[j] += TMath::Power(r,w)*TMath::Cos(j*phi);
           sinphi[j] += TMath::Power(r,w)*TMath::Sin(j*phi);
           rn[j]     += TMath::Power(r,w);
         }
       }
     }
     for (Int_t j = 1; j<9; ++j) {
       psi[j] = (TMath::ATan2(sinphi[j],cosphi[j]) + TMath::Pi())/j;
       ecc[j] = TMath::Sqrt(sinphi[j]*sinphi[j] + cosphi[j]*cosphi[j]) / rn[j];
     }
 
     Float_t v[27]; Int_t i=0;
     v[i++] = mcg->GetNpart();
     v[i++] = mcg->GetNcoll();
     v[i++] = mcg->GetB();
     v[i++] = mcg->GetPsi(1); // point-like calculation values
     v[i++] = mcg->GetEcc(1);
     v[i++] = mcg->GetPsi(2);
     v[i++] = mcg->GetEcc(2);
     v[i++] = mcg->GetPsi(3);
     v[i++] = mcg->GetEcc(3);
     v[i++] = mcg->GetPsi(4);
     v[i++] = mcg->GetEcc(4);
     v[i++] = mcg->GetPsi(5);
     v[i++] = mcg->GetEcc(5);
     v[i++] = psi[1];         // Gaussian smeared values
     v[i++] = ecc[1];
     v[i++] = psi[2];
     v[i++] = ecc[2];
     v[i++] = psi[3];
     v[i++] = ecc[3];
     v[i++] = psi[4];
     v[i++] = ecc[4];
     v[i++] = psi[5];
     v[i++] = ecc[5];
     v[i++] = mcg->GetSx2();
     v[i++] = mcg->GetSy2();
     v[i++] = sx2g/NSAMP;
     v[i++] = sy2g/NSAMP;
     nt->Fill(v);
   }
 
   out->Write();
   out->Close();
   delete out;
 }
 
 //---------------------------------------------------------------------------------
 void runAndCalcDens(const Int_t n,
 		    const Double_t alpha,
 		    const char *sysA,
 		    const char *sysB,
 		    const Double_t signn,
 		    const Double_t mind,
 		    const char *fname)
 {
   // Run Glauber and store per event a density profile in x and y, calculated from participant and binary positions
   // with relative weight given by alpha.
 
   TGlauberMC *mcg = new TGlauberMC(sysA,sysB,signn);
   mcg->SetMinDistance(mind);
 
   TFile *out = 0;
   TCanvas *c1 = 0;
   if (fname) {
     out = TFile::Open(fname,"recreate",fname,9);
     if (!out)
       return;
   } else {
     c1 = new TCanvas;
   }
 
   const Int_t NSAMP = 100;
   const Double_t wp = (1-alpha)/2;
   const Double_t wb = alpha;
   const Double_t sigs = TMath::Sqrt(signn/20/TMath::Pi()); //from arXiv::0711.3724
 
 
   TF1 *rad = new TF1("rad","x*TMath::Exp(-x*x/(2.*[0]*[0]))",0.0,3*sigs);
   rad->SetParameter(0,sigs);
 
   TH2F *h2f = new TH2F("h2f",";x (fm);y (fm)",121,-15.5,15.5,121,-15.5,15.5);
   h2f->SetStats(0);
   
   for (Int_t ievent=0; ievent<n; ++ievent) {
     while (!mcg->NextEvent()) {}
     h2f->Reset();
     h2f->SetName(Form("Event_%d",ievent));
     h2f->SetTitle(Form("Npart=%d, Ncoll=%d",mcg->GetNpart(), mcg->GetNcoll()));
 
     const TGlauNucleus *nucA   = mcg->GetNucleusA();
     const TObjArray *nucleonsA = nucA->GetNucleons();
     const Int_t AN             = nucA->GetN();
     const TGlauNucleus *nucB   = mcg-> GetNucleusB();
     const TObjArray *nucleonsB = nucB->GetNucleons();
     const Int_t BN             = nucB->GetN();
 
     for (Int_t i = 0; i<AN; ++i) {
       TGlauNucleon *nucleonA=(TGlauNucleon*)(nucleonsA->At(i));
       if (!nucleonA->IsWounded())
 	continue;
       Double_t xA=nucleonA->GetX();
       Double_t yA=nucleonA->GetY();
       for (Int_t s=0; s<NSAMP; ++s) {
 	Double_t sr = rad->GetRandom();
 	Double_t sp = gRandom->Uniform(-TMath::Pi(), +TMath::Pi());
 	h2f->Fill(xA+sr*TMath::Cos(sp),yA+sr*TMath::Sin(sp),wp);
       }
     }
 
     for (Int_t j = 0; j<BN; ++j) {
       TGlauNucleon *nucleonB=(TGlauNucleon*)(nucleonsB->At(j));
       if (!nucleonB->IsWounded())
 	continue;
       Double_t xB=nucleonB->GetX();
       Double_t yB=nucleonB->GetY();
       for (Int_t s=0; s<NSAMP; ++s) {
 	Double_t sr = rad->GetRandom();
 	Double_t sp = gRandom->Uniform(-TMath::Pi(), +TMath::Pi());
 	h2f->Fill(xB+sr*TMath::Cos(sp),yB+sr*TMath::Sin(sp),wp);
       }
     }
 
     if (alpha>0) {
       for (Int_t i = 0; i<AN; ++i) {
 	TGlauNucleon *nucleonA=(TGlauNucleon*)(nucleonsA->At(i));
 	if (!nucleonA->IsWounded())
 	  continue;
 	Double_t xA=nucleonA->GetX();
 	Double_t yA=nucleonA->GetY();
 	for (Int_t j = 0; j<BN; ++j) {
 	  TGlauNucleon *nucleonB=(TGlauNucleon*)(nucleonsB->At(j));
 	  if (!mcg->IsBC(i,j))
 	    continue;
 	  Double_t xB=nucleonB->GetX();
 	  Double_t yB=nucleonB->GetY();
 	  Double_t dX=(xA+xB)/2;
 	  Double_t dY=(yA+yB)/2;
 	  for (Int_t s=0; s<NSAMP; ++s) {
 	    Double_t sr = rad->GetRandom();
 	    Double_t sp = gRandom->Uniform(-TMath::Pi(), +TMath::Pi());
 	    h2f->Fill(dX+sr*TMath::Cos(sp),dY+sr*TMath::Sin(sp),wb);
 	  }
 	}
       }
     }
     h2f->Scale(1./h2f->Integral());
     if (out) {
       h2f->Write();
     } else {
       h2f->Draw("colz");
       c1->Update();
       gSystem->Sleep(1000);
     }
   }
   if (out) {
     out->Write();
     out->Close();
     delete out;
   }
 }
 
 //---------------------------------------------------------------------------------
 ClassImp(TGlauNucleus)
 //---------------------------------------------------------------------------------
 TGlauNucleus::TGlauNucleus(const char* iname, Int_t iN, Double_t iR, Double_t ia, Double_t iw, TF1* ifunc) : 
   TNamed(iname,""),
   fN(iN),fR(iR),fA(ia),fW(iw),fR2(0),fA2(0),fW2(0),fBeta2(0),fBeta4(0),
   fMinDist(0.4),fNodeDist(0.0),fSmearing(0.0),fRecenter(1),fLattice(0),fSmax(99),
   fF(0),fTrials(0),fNonSmeared(0),fFunc1(ifunc),fFunc2(0),fFunc3(0),fNucleons(0),
   fPhiRot(0),fThetaRot(0),fHe3Counter(-1),fIsUsed(0),fMaxR(14)
 {
   if (fN==0) {
     cout << "Setting up nucleus " << iname << endl;
     Lookup(iname);
   }
 }
 
 TGlauNucleus::~TGlauNucleus()
 {
   if (fIsUsed)
     delete fIsUsed;
   if (fNucleons)
     delete fNucleons;
   delete fFunc1;
   delete fFunc2;
   delete fFunc3;
 }
 
 void TGlauNucleus::Draw(Double_t xs, Int_t colp, Int_t cols)
 {
   Double_t r = 0.5*TMath::Sqrt(xs/TMath::Pi()/10.);
   TEllipse en;
   en.SetLineStyle(1);
   en.SetLineWidth(1);
   en.SetFillStyle(1001);
   for (Int_t i = 0; i<fNucleons->GetEntries(); ++i) {
     TGlauNucleon* gn = (TGlauNucleon*) fNucleons->At(i);
     if (!gn->IsSpectator()) {
       en.SetFillColor(colp);
       en.DrawEllipse(gn->GetX(),gn->GetY(),r,r,0,360,0,"");
     } else {
       en.SetFillColor(cols);
       en.SetFillStyle(1001);
       en.DrawEllipse(gn->GetX(),gn->GetY(),r,r,0,360,0,"");
     }
   }
 }
 
 void TGlauNucleus::Lookup(const char* name)
 {
   SetName(name);
 
   TString tmp(name);
 
   Double_t r0 = 0;
   Double_t r1 = 0;
   Double_t r2 = 0;
 
   if      (TString(name) == "p")       {fN = 1;   fR = 0.234;      fA = 0;      fW =  0;       fF = 0;  fZ=1;}
   else if (TString(name) == "pg")      {fN = 1;   fR = 0.514;      fA = 0;      fW =  0;       fF = 9;  fZ=1;} 
   else if (TString(name) == "pdg")     {fN = 1;   fR = 1;          fA = 0;      fW =  0;       fF = 10; fZ=1;} // from arXiv:1101.5953
   else if (TString(name) == "d")       {fN = 2;   fR = 0.01;       fA = 0.5882; fW =  0;       fF = 1;  fZ=1;}
   else if (TString(name) == "dh")      {fN = 2;   fR = 0.01;       fA = 0.5882; fW =  0;       fF = 3;  fZ=1;}
   else if (TString(name) == "dhh")     {fN = 2;   fR = 0.01;       fA = 0.5882; fW =  0;       fF = 4;  fZ=1;}
   else if (TString(name) == "He3")     {fN = 3;   fR = 0.01;       fA = 0.5882; fW =  0;       fF = 6;  fZ=1;}
   else if (TString(name) == "H3")      {fN = 3;   fR = 0.01;       fA = 0.5882; fW =  0;       fF = 6;  fZ=2;}
   else if (TString(name) == "O")       {fN = 16;  fR = 2.608;      fA = 0.513;  fW = -0.051;   fF = 1;  fZ=8;}
   else if (TString(name) == "Si")      {fN = 28;  fR = 3.34;       fA = 0.580;  fW = -0.233;   fF = 1;  fZ=14;}
   else if (TString(name) == "Si2")     {fN = 28;  fR = 3.34;       fA = 0.580;  fW =  0;       fF = 8;  fZ=14; fBeta2=-0.478; fBeta4=0.250;}
   else if (TString(name) == "S")       {fN = 32;  fR = 2.54;       fA = 2.191;  fW =  0.16;    fF = 2;  fZ=16;}
   else if (TString(name) == "Ar")      {fN = 40;  fR = 3.53;       fA = 0.542;  fW =  0;       fF = 1;  fZ=18;}
   else if (TString(name) == "Ca")      {fN = 40;  fR = 3.766;      fA = 0.586;  fW = -0.161;   fF = 1;  fZ=20;}
   else if (TString(name) == "Ni")      {fN = 58;  fR = 4.309;      fA = 0.517;  fW = -0.1308;  fF = 1;  fZ=28;}
   else if (TString(name) == "Cu")      {fN = 63;  fR = 4.20;       fA = 0.596;  fW =  0;       fF = 1;  fZ=29;}
   else if (TString(name) == "Curw ")   {fN = 63;  fR = 4.20;       fA = 0.596;  fW =  0;       fF = 12; fZ=29; r0=1.00898; r1=-0.000790403; r2=-0.000389897;} 
   else if (TString(name) == "Cu2")     {fN = 63;  fR = 4.20;       fA = 0.596;  fW =  0;       fF = 8;  fZ=29; fBeta2=0.162; fBeta4=-0.006;}  
   else if (TString(name) == "Cu2rw")   {fN = 63;  fR = 4.20;       fA = 0.596;  fW =  0;       fF = 14; fZ=29; fBeta2=0.162; fBeta4=-0.006; r0=1.01269; r1=-0.00298083; r2=-9.97222e-05;}  
   else if (TString(name) == "CuHN")    {fN = 63;  fR = 4.28;       fA = 0.5;    fW =  0;       fF = 1;  fZ=29;} // from arXiv:0904.4080v1
   else if (TString(name) == "Xe")      {fN = 129; fR = 5.36;       fA = 0.59;   fW =  0;       fF = 1;  fZ=54;} // adapted from arXiv:1703.04278
   else if (TString(name) == "Xes")     {fN = 129; fR = 5.42;       fA = 0.57;   fW =  0;       fF = 1;  fZ=54;} // scale from Sb (Antimony, A=122, r=5.32) by 1.019 = (129/122)**0.333
   else if (TString(name) == "Xe2")     {fN = 129; fR = 5.36;       fA = 0.59;   fW =  0;       fF = 8;  fZ=54; fBeta2=0.161; fBeta4=-0.003;} // adapted from arXiv:1703.04278 and Z. Physik (1974) 270: 113
   else if (TString(name) == "Xe2a")    {fN = 129; fR = 5.36;       fA = 0.59;   fW =  0;       fF = 8;  fZ=54; fBeta2=0.18; fBeta4=0;} // ALICE parameters (see public note from 2018 at https://cds.cern.ch/collection/ALICE%20Public%20Notes?ln=en)
   else if (TString(name) == "Xerw")    {fN = 129; fR = 5.36;       fA = 0.59;   fW =  0;       fF = 12; fZ=54; r0=1.00911; r1=-0.000722999; r2=-0.0002663;}
   else if (TString(name) == "Xesrw")   {fN = 129; fR = 5.42;       fA = 0.57;   fW =  0;       fF = 12; fZ=54; r0=1.0096; r1=-0.000874123; r2=-0.000256708;}
   else if (TString(name) == "Xe2arw")  {fN = 129; fR = 5.36;       fA = 0.59;   fW =  0;       fF = 14; fZ=54; fBeta2=0.18; fBeta4=0; r0=1.01246; r1=-0.0024851; r2=-5.72464e-05;} 
   else if (TString(name) == "W")       {fN = 186; fR = 6.58;       fA = 0.480;  fW =  0;       fF = 1;  fZ=74;}
   else if (TString(name) == "Au")      {fN = 197; fR = 6.38;       fA = 0.535;  fW =  0;       fF = 1;  fZ=79;}
   else if (TString(name) == "Aurw")    {fN = 197; fR = 6.38;       fA = 0.535;  fW =  0;       fF = 12; fZ=79; r0=1.00899; r1=-0.000590908; r2=-0.000210598;}
   else if (TString(name) == "Au2")     {fN = 197; fR = 6.38;       fA = 0.535;  fW =  0;       fF = 8;  fZ=79; fBeta2=-0.131; fBeta4=-0.031; }
   else if (TString(name) == "Au2rw")   {fN = 197; fR = 6.38;       fA = 0.535;  fW =  0;       fF = 14; fZ=79; fBeta2=-0.131; fBeta4=-0.031; r0=1.01261; r1=-0.00225517; r2=-3.71513e-05;}
   else if (TString(name) == "AuHN")    {fN = 197; fR = 6.42;       fA = 0.44;   fW =  0;       fF = 1;  fZ=79;} // from arXiv:0904.4080v1
   else if (TString(name) == "Pb")      {fN = 208; fR = 6.62;       fA = 0.546;  fW =  0;       fF = 1;  fZ=82;}
   else if (TString(name) == "Pbrw")    {fN = 208; fR = 6.62;       fA = 0.546;  fW =  0;       fF = 12; fZ=82; r0=1.00863; r1=-0.00044808; r2=-0.000205872;} //only Pb 207 was tested but should be the same for 208
   else if (TString(name) == "Pb*")     {fN = 208; fR = 6.624;      fA = 0.549;  fW =  0;       fF = 1;  fZ=82;}
   else if (TString(name) == "PbHN")    {fN = 208; fR = 6.65;       fA = 0.460;  fW =  0;       fF = 1;  fZ=82;}
   else if (TString(name) == "Pbpn")    {fN = 208; fR = 6.68;       fA = 0.447;  fW =  0;       fF = 11; fZ=82; fR2=6.69; fA2=0.56; fW2=0;}
   else if (TString(name) == "Pbpnrw")  {fN = 208; fR = 6.68;       fA = 0.447;  fW =  0;       fF = 13; fZ=82; fR2=6.69; fA2=0.56; fW2=0;}
   // Uranium description taken from Heinz & Kuhlman, nucl-th/0411054.  In this code, fR is defined as 6.8*0.91, fW=6.8*0.26
   else if (TString(name) == "U")       {fN = 238; fR = 6.188;      fA = 0.54;   fW =  1.77;    fF = 5;  fZ=92;}  
   else if (TString(name) == "U2")      {fN = 238; fR = 6.67;       fA = 0.44;   fW =  0;       fF = 8;  fZ=92; fBeta2=0.280; fBeta4=0.093;}
   else {
     cout << "Could not find nucleus " << name << endl;
     return;
   }
 
   switch (fF) {
     case 0: // Proton exp
       fFunc1 = new TF1("prot","x*x*exp(-x/[0])",0,5);
       fFunc1->SetParameter(0,fR);
       break;
     case 1: // 3pF
       fFunc1 = new TF1(name,"x*x*(1+[2]*(x/[0])**2)/(1+exp((x-[0])/[1]))",0,fMaxR);
       fFunc1->SetParameters(fR,fA,fW);
       break;
     case 2: // 3pG
       fFunc1 = new TF1("3pg","x*x*(1+[2]*(x/[0])**2)/(1+exp((x**2-[0]**2)/[1]**2))",0,fMaxR);
       fFunc1->SetParameters(fR,fA,fW);
       break;
     case 3: // Hulthen (see nucl-ex/0603010)
       fFunc1 = new TF1("f3","x*x*([0]*[1]*([0]+[1]))/(2*pi*(pow([0]-[1],2)))*pow((exp(-[0]*x)-exp(-[1]*x))/x,2)",0,fMaxR);
       fFunc1->SetParameters(1/4.38,1/.85);
       break;
     case 4: // Hulthen HIJING
       fFunc1 = new TF1("f4","x*x*([0]*[1]*([0]+[1]))/(2*pi*(pow([0]-[1],2)))*pow((exp(-[0]*x)-exp(-[1]*x))/x,2)",0,fMaxR);
       fFunc1->SetParameters(2/4.38,2/.85);
       break;
     case 5: // Ellipsoid (Uranium)
       fFunc1 = new TF1(name,"x*x*(1+[2]*(x/[0])**2)/(1+exp((x-[0])/[1]))",0,fMaxR);
       fFunc1->SetParameters(fR,fA,0); // same as 3pF but setting W to zero
       break;
     case 6: // He3/H3
       fFunc1 = 0; // read in file instead
       break;
     case 7: // Deformed nuclei, box method
 #ifndef HAVE_MATHMORE
       cerr << "Need libMathMore.so for deformed nuclei" << endl;
       gSystem->Exit(123);
 #endif
      fFunc1 = 0; // no func: only need beta parameters and use uniform box distribution
       break;
     case 8: // Deformed nuclei, TF2 method
       fFunc3 = new TF2("f77","x*x*TMath::Sin(y)/(1+exp((x-[0]*(1+[2]*0.315*(3*pow(cos(y),2)-1.0)+[3]*0.105*(35*pow(cos(y),4)-30*pow(cos(y),2)+3)))/[1]))",0,fMaxR,0.0,TMath::Pi());
       fFunc3->SetNpx(120);
       fFunc3->SetNpy(120);
       fFunc3->SetParameters(fR,fA,fBeta2,fBeta4);
       break;
     case 9: // Proton gaus
       fFunc1 = new TF1("prot","x*x*exp(-x*x/[0]/[0]/2)",0,5);
       fFunc1->SetParameter(0,fR);
       break;
     case 10: // Proton dgaus
       fFunc1 = new TF1("prot","x*x*((1-[0])/[1]^3*exp(-x*x/[1]/[1])+[0]/(0.4*[1])^3*exp(-x*x/(0.4*[1])^2))",0,5);
       fFunc1->SetParameter(0,0.5);
       fFunc1->SetParameter(1,fR);
       break;
     case 11: // 3pF for proton and neutrons
       fFunc1 = new TF1(name,"x*x*(1+[2]*(x/[0])**2)/(1+exp((x-[0])/[1]))",0,fMaxR);
       fFunc1->SetParameters(fR,fA,fW);
       fFunc2 = new TF1(name,"x*x*(1+[2]*(x/[0])**2)/(1+exp((x-[0])/[1]))",0,fMaxR);
       fFunc2->SetParameters(fR2,fA2,fW2);
       break;
     case 12: // reweighted
       fFunc1 = new TF1(name,"x*x*(1+[2]*(x/[0])**2)/(1+exp((x-[0])/[1]))/([3]+[4]*x+[5]*x^2)",0,fMaxR);
       fFunc1->SetParameters(fR,fA,fW,r0,r1,r2); 
       fRecenter=1;
       fSmax=0.1;
       break;
     case 13: // Pb for proton and neutrons reweighted
       fFunc1 = new TF1(Form("%s_prot",name),"x*x*(1+[2]*(x/[0])**2)/(1+exp((x-[0])/[1]))/([3]+[4]*x+[5]*x^2)",0,fMaxR);
       fFunc1->SetParameters(fR,fA,fW,1.00866,-0.000461484,-0.000203571);
       fFunc2 = new TF1(Form("%s_neut",name),"x*x*(1+[2]*(x/[0])**2)/(1+exp((x-[0])/[1]))/([3]+[4]*x+[5]*x^2)",0,fMaxR);
       fFunc2->SetParameters(fR2,fA2,fW2,1.00866,-0.000461484,-0.000203571);
       fRecenter=1;
       fSmax=0.1;
       break;
     case 14: // Deformed nuclei, TF2 method, reweighted
       fFunc3 = new TF2("f77","x*x*TMath::Sin(y)/(1+exp((x-[0]*(1+[2]*0.315*(3*pow(cos(y),2)-1.0)+[3]*0.105*(35*pow(cos(y),4)-30*pow(cos(y),2)+3)))/[1]))/([4]+[5]*x+[6]*x^2)",0,fMaxR,0.0,TMath::Pi());
       fFunc3->SetNpx(120);
       fFunc3->SetNpy(120);
       fFunc3->SetParameters(fR,fA,fBeta2,fBeta4,r0,r1,r2);
       fRecenter=1;
       fSmax=0.1;
       break;
     default:
       cerr << "Could not find function type " << fF << endl;
   }
   return;
 }
 
 void TGlauNucleus::SetA(Double_t ia, Double_t ia2)
 {
   fA  = ia;
   fA2 = ia2;
   switch (fF) {
     case 1:  // 3pF
     case 12: // 3pF with pol2 normalization
     case 2:  // 3pG
     case 5:  // Ellipsoid (Uranium)
       fFunc1->SetParameter(1,fA);
       break;
     case 8:
       fFunc3->SetParameter(1,fA);
       break;
     case 11: //p&n
       fFunc1->SetParameter(1,fA);//proton
       fFunc2->SetParameter(1,fA2);//neutron
       break;
     default:
       cout << "Error: fA not needed for function " << fF <<endl;
   }
 }
 
 void TGlauNucleus::SetBeta(Double_t b2, Double_t b4) 
 {
   fBeta2=b2; 
   fBeta4=b4;      
   if (fFunc3) {
     fFunc3->SetParameter(2,fBeta2);
     fFunc3->SetParameter(3,fBeta4);
   }
 }
 
 void TGlauNucleus::SetR(Double_t ir, Double_t ir2)
 {
   fR  = ir;
   fR2 = ir2;
   switch (fF) {
     case 0:  // Proton exp
     case 9:  // Proton gaus
     case 1:  // 3pF
     case 12: // 3pF with pol2 normalization
     case 2:  // 3pG
     case 5:  // Ellipsoid (Uranium)
       fFunc1->SetParameter(0,fR);
       break;
     case 8:
       fFunc3->SetParameter(0,fR);
       break;
     case 10: // Proton
       fFunc1->SetParameter(1,fR);
       break;
     case 11: // p&n
       fFunc1->SetParameter(0,fR);//proton
       fFunc2->SetParameter(0,fR2);//neutron
       break;
     default:
       cout << "Error: fR not needed for function " << fF <<endl;
   }
 }
 
 void TGlauNucleus::SetW(Double_t iw)
 {
   fW = iw;
   switch (fF) {
     case 1: // 3pF
     case 2: // 3pG
       fFunc1->SetParameter(2,fW);
       break;
     default:
       cout << "Error: fW not needed for function " << fF <<endl;
   }
 }
 
 Bool_t TGlauNucleus::TestMinDist(Int_t n, Double_t x, Double_t y, Double_t z) const
 {
   if (fMinDist<=0)
     return kTRUE;
   const Double_t md2 = fMinDist*fMinDist; 
   for (Int_t j = 0; j<n; ++j) {
     TGlauNucleon *other=(TGlauNucleon*)fNucleons->At(j);
     Double_t xo=other->GetX();
     Double_t yo=other->GetY();
     Double_t zo=other->GetZ();
     Double_t dist2 = (x-xo)*(x-xo)+
 		                 (y-yo)*(y-yo)+
 		                 (z-zo)*(z-zo);
     if (dist2<md2) {
       return kFALSE;
     }
   }
   return kTRUE;
 }
 
 TVector3 &TGlauNucleus::ThrowNucleons(Double_t xshift)
 {
   if (fNucleons==0) {
     fNucleons=new TObjArray(fN);
     fNucleons->SetOwner();
     for (Int_t i=0; i<fN; ++i) {
       TGlauNucleon *nucleon=new TGlauNucleon(); 
       nucleon->SetType(0);
       if (i<fZ) 
         nucleon->SetType(1);
       fNucleons->Add(nucleon); 
     }
   } 
   if (1) { //randomize p and n in nucleus
     for (Int_t i=0,iz=0; i<fN; ++i) {
       TGlauNucleon *nucleon=(TGlauNucleon*)fNucleons->At(i);
       Double_t frac=double(fZ-iz)/double(fN-i);
       Double_t rn=gRandom->Uniform(0,1);
       if (rn<frac) {
         nucleon->SetType(1);
         ++iz;
       } else {
         nucleon->SetType(0);
       }
     }
   }
  cmscheck: /* start over here in case shift was too large */
   fTrials = 0;
   fNonSmeared = 0;
   fPhiRot = gRandom->Rndm()*2*TMath::Pi();
   const Double_t cosThetaRot = 2*gRandom->Rndm()-1;
   fThetaRot = TMath::ACos(cosThetaRot);
   fXRot = gRandom->Rndm()*2*TMath::Pi();
   fYRot = gRandom->Rndm()*2*TMath::Pi();
   fZRot = gRandom->Rndm()*2*TMath::Pi();
   const Bool_t hulthen = (TString(GetName())=="dh" || TString(GetName())=="dhh");
   const Bool_t helium3 = (TString(GetName())=="He3") || (TString(GetName())=="H3");
   if (fN==1) { //special treatment for proton
     Double_t r = fFunc1->GetRandom();
     Double_t phi = gRandom->Rndm() * 2 * TMath::Pi();
     Double_t ctheta = 2*gRandom->Rndm() - 1;
     Double_t stheta = TMath::Sqrt(1-ctheta*ctheta);
     TGlauNucleon *nucleon=(TGlauNucleon*)(fNucleons->At(0));
     nucleon->Reset();
     nucleon->SetXYZ(r * stheta * TMath::Cos(phi),
 		    r * stheta * TMath::Sin(phi),
 		    r * ctheta);
     fTrials = 1;
   } else if (fN==2 && hulthen) { //special treatment for Hulten
     Double_t r = fFunc1->GetRandom()/2;
     Double_t phi = gRandom->Rndm() * 2 * TMath::Pi();
     Double_t ctheta = 2*gRandom->Rndm() - 1;
     Double_t stheta = TMath::Sqrt(1-ctheta*ctheta);
 
     TGlauNucleon *nucleon1=(TGlauNucleon*)(fNucleons->At(0));
     TGlauNucleon *nucleon2=(TGlauNucleon*)(fNucleons->At(1));
     nucleon1->Reset();
     nucleon1->SetXYZ(r * stheta * TMath::Cos(phi),
                      r * stheta * TMath::Sin(phi),
                      r * ctheta);
     nucleon2->Reset();
     nucleon2->SetXYZ(-nucleon1->GetX(),
                      -nucleon1->GetY(),
                      -nucleon1->GetZ());
     fTrials = 1;
   } else if (helium3) { 
     if (fHe3Counter == -1) {
       // read in the ascii file into the array and step through the counter
       char filename[100] = "he3_plaintext.dat";
       if ((TString(GetName())=="H3")) {
         sprintf(filename,"h3_plaintext.dat");
       }
       cout << "Reading in the " << filename << " file upon initialization" << endl;
       ifstream myfile;
       myfile.open(filename);
       if (!myfile) {
         cout << "ERROR:  no file for He3/H3 found with name = " << filename << endl;
         gSystem->Exit(123);
       }
       cout << "Reading file for He3/H3 found with name = " << filename << endl;
       Int_t inputcounter = 0;
       while (myfile) {
-        if (inputcounter > 6000) break;
+        if (inputcounter > 5999) break;
         Double_t foo;
         myfile >> fHe3Arr[inputcounter][0][0] >> fHe3Arr[inputcounter][0][1] >> fHe3Arr[inputcounter][0][2]
                >> fHe3Arr[inputcounter][1][0] >> fHe3Arr[inputcounter][1][1] >> fHe3Arr[inputcounter][1][2]
                >> fHe3Arr[inputcounter][2][0] >> fHe3Arr[inputcounter][2][1] >> fHe3Arr[inputcounter][2][2]
                >> foo >> foo >> foo >> foo;
         ++inputcounter;
       }  
       myfile.close();
       fHe3Counter=0;
     } // done reading in the file the first time
     if (fHe3Counter > 5999) 
       fHe3Counter = 0;
     TGlauNucleon *nucleon1=(TGlauNucleon*)(fNucleons->At(0));
     TGlauNucleon *nucleon2=(TGlauNucleon*)(fNucleons->At(1));
     TGlauNucleon *nucleon3=(TGlauNucleon*)(fNucleons->At(2));
     nucleon1->Reset();
     nucleon1->SetXYZ(fHe3Arr[fHe3Counter][0][0],
                      fHe3Arr[fHe3Counter][0][1],
                      fHe3Arr[fHe3Counter][0][2]);
     nucleon1->RotateXYZ(fPhiRot,fThetaRot);
     nucleon2->Reset();
     nucleon2->SetXYZ(fHe3Arr[fHe3Counter][1][0],
                      fHe3Arr[fHe3Counter][1][1],
                      fHe3Arr[fHe3Counter][1][2]);
     nucleon2->RotateXYZ(fPhiRot,fThetaRot);
     nucleon3->Reset();
     nucleon3->SetXYZ(fHe3Arr[fHe3Counter][2][0],
                      fHe3Arr[fHe3Counter][2][1],
                      fHe3Arr[fHe3Counter][2][2]);
     nucleon3->RotateXYZ(fPhiRot,fThetaRot);
     ++fHe3Counter;
     fTrials = 1;
   } else { // all other nuclei 
     const Double_t startingEdge  = 20; // throw nucleons within a cube of this size (fm)
     const Double_t startingEdgeX = startingEdge + fNodeDist*gRandom->Rndm() - 0.5*fNodeDist;
     const Double_t startingEdgeY = startingEdge + fNodeDist*gRandom->Rndm() - 0.5*fNodeDist;
     const Double_t startingEdgeZ = startingEdge + fNodeDist*gRandom->Rndm() - 0.5*fNodeDist;
     const Int_t nslots = 2*startingEdge/fNodeDist+1;
     if (fNodeDist>0) {
       if (fMinDist>fNodeDist) {
         cout << "Minimum distance (nucleon hard core diameter) [" 
           << fMinDist << "] cannot be larger than the nodal spacing of the grid [" 
           << fNodeDist << "]." << endl;
         cout << "Quitting...." << endl;
         gSystem->Exit(123);
       }
       if (!fIsUsed)
         fIsUsed = new TBits(nslots*nslots*nslots);
       else
         fIsUsed->ResetAllBits();
     }
     for (Int_t i = 0; i<fN; ++i) {
       TGlauNucleon *nucleon=(TGlauNucleon*)(fNucleons->At(i));
       nucleon->Reset();
       while (1) {
         ++fTrials;
         Bool_t nucleon_inside = 0;
         Double_t x=999, xsmeared=999;
         Double_t y=999, ysmeared=999;
         Double_t z=999, zsmeared=999;
         if (fF==5||fF==7) { // the extended way, throw in a box and test the weight
           while (!nucleon_inside) {
             x = (fR*2)*(gRandom->Rndm() * 2 - 1);
             y = (fR*2)*(gRandom->Rndm() * 2 - 1);
             z = (fR*2)*(gRandom->Rndm() * 2 - 1);
             Double_t r = TMath::Sqrt(x*x+y*y);
             Double_t theta = TMath::ATan2(r,z);
             Double_t R = TMath::Sqrt(x*x+y*y+z*z);
             Double_t Rtheta = fR;
             if (fF==5)
               Rtheta= fR + fW*TMath::Cos(theta)*TMath::Cos(theta);
             if (fF==7)
 #ifdef HAVE_MATHMORE
               Rtheta = fR*(1+fBeta2*ROOT::Math::sph_legendre(2,0,theta)+fBeta4*ROOT::Math::sph_legendre(4,0,theta));
 #else
             cerr << "Should not end here because you do not have libMathMore" << endl;
 #endif
             Double_t prob = 1/(1+TMath::Exp((R-Rtheta)/fA));
             if (gRandom->Rndm()<prob) 
               nucleon_inside=1;
           }
         } else if ((fF==8) || (fF==14)) { // use TF2
           Double_t r;
           Double_t theta;
           fFunc3->GetRandom2(r,theta);
           Double_t phi = 2*TMath::Pi()*gRandom->Rndm();
           x = r * TMath::Sin(phi) * TMath::Sin(theta);
           y = r * TMath::Cos(phi) * TMath::Sin(theta);
           z = r *                   TMath::Cos(theta);
         } else { // all other types
           TF1 *ff = fFunc1;
           if ((fFunc2) && (nucleon->GetType()==0))
             ff = fFunc2;
           if (fNodeDist<=0) { // "continuous" mode
             Double_t r = ff->GetRandom();
             Double_t phi = 2*TMath::Pi()*gRandom->Rndm();
             Double_t ctheta = 2*gRandom->Rndm() - 1 ;
             Double_t stheta = TMath::Sqrt(1-ctheta*ctheta);
             x = r * stheta * TMath::Cos(phi);
             y = r * stheta * TMath::Sin(phi);
             z = r * ctheta;
           } else { // "grid/lattice" mode
             Int_t iNode = Int_t((2*startingEdge/fNodeDist)*gRandom->Rndm());
             Int_t jNode = Int_t((2*startingEdge/fNodeDist)*gRandom->Rndm());
             Int_t kNode = Int_t((2*startingEdge/fNodeDist)*gRandom->Rndm());
             Int_t index=iNode*nslots*nslots+jNode*nslots+kNode;
             if (fIsUsed->TestBitNumber(index))
               continue;
             if (fLattice==1) {       // Primitive cubic system (PCS) -> https://en.wikipedia.org/wiki/Cubic_crystal_system
               x = fNodeDist*(iNode) - startingEdgeX;
               y = fNodeDist*(jNode) - startingEdgeY;
               z = fNodeDist*(kNode) - startingEdgeZ;
             } else if (fLattice==2) { //Body centered cubic (BCC) -> http://mathworld.wolfram.com/CubicClosePacking.html
               x = 0.5*fNodeDist*(-iNode+jNode+kNode) - 0.5*startingEdgeX;
               y = 0.5*fNodeDist*(+iNode-jNode+kNode) - 0.5*startingEdgeY;
               z = 0.5*fNodeDist*(+iNode+jNode-kNode) - 0.5*startingEdgeZ;
             } else if (fLattice==3) { //Face Centered Cubic (FCC) -> http://mathworld.wolfram.com/CubicClosePacking.html
               x = 0.5*fNodeDist*(jNode+kNode) - startingEdgeX;
               y = 0.5*fNodeDist*(iNode+kNode) - startingEdgeY;
               z = 0.5*fNodeDist*(iNode+jNode) - startingEdgeZ;
             } else {                  //Hexagonal close packing (HCP) -> https://en.wikipedia.org/wiki/Close-packing_of_equal_spheres
               x = 0.5*fNodeDist*(2*iNode+((jNode+kNode)%2))          - startingEdgeX;
               y = 0.5*fNodeDist*(TMath::Sqrt(3)*(jNode+(kNode%2)/3)) - startingEdgeY;
               z = 0.5*fNodeDist*(kNode*2*TMath::Sqrt(6)/3)           - startingEdgeZ;
             }
             const Double_t r2 = x*x + y*y + z*z;
             const Double_t r  = TMath::Sqrt(r2);
 	    if ((r>fMaxR)||(r2*gRandom->Rndm()>ff->Eval(r)))
 	      continue;
             if (fSmearing>0.0) {
               Int_t nAttemptsToSmear = 0;
               while (1) {
                 xsmeared = x*gRandom->Gaus(1.0,fSmearing);
                 ysmeared = y*gRandom->Gaus(1.0,fSmearing);
                 zsmeared = z*gRandom->Gaus(1.0,fSmearing);
                 nAttemptsToSmear++;
                 if (TestMinDist(i,xsmeared,ysmeared,zsmeared)) {
                   x = xsmeared;
                   y = ysmeared;
                   z = zsmeared;
                   break;
                 }
                 if (nAttemptsToSmear>=99) {
                   cerr << "Could not place on this node :: [" << x <<","<< y <<","<< z <<"] r = " << TMath::Sqrt(x*x+y*y+z*z) << " fm; "
                     << "Node (" << iNode << "," << jNode << "," << kNode << ") not smeared !!!" << endl;
                   ++fNonSmeared;
                   break;
                 }
               }
             }
             fIsUsed->SetBitNumber(index);
           } /* end "grid/lattice mode" */
 	}
 	nucleon->SetXYZ(x,y,z);
 	if (fF==5||fF==7||fF==8||fF==14) 
 	  nucleon->RotateXYZ(fPhiRot,fThetaRot); // Uranium etc.
 	if (fNodeDist>0) {
 	  nucleon->RotateXYZ_3D(fXRot,fYRot,fZRot);
 	  break;
 	}
 	if (TestMinDist(i,x,y,z))
 	  break;
       }
     }
   }    
 
   // calculate center of mass
   Double_t sumx=0;       
   Double_t sumy=0;       
   Double_t sumz=0;       
   for (Int_t i = 0; i<fN; ++i) {
     TGlauNucleon *nucleon=(TGlauNucleon*)(fNucleons->At(i));
     sumx += nucleon->GetX();
     sumy += nucleon->GetY();
     sumz += nucleon->GetZ();
   }
   sumx = sumx/fN;
   sumy = sumy/fN;
   sumz = sumz/fN;
   static TVector3 finalShift;
   finalShift.SetXYZ(sumx,sumy,sumz);
   if (finalShift.Mag()>fSmax)
     goto cmscheck;
   Double_t fsumx = 0;
   Double_t fsumy = 0;
   Double_t fsumz = 0;
   if (fRecenter==1) {
     fsumx = sumx;
     fsumy = sumy;
     fsumz = sumz;
   } else if (fRecenter==2) {
     TGlauNucleon *nucleon=(TGlauNucleon*)(fNucleons->At(fN-1));
     Double_t x = nucleon->GetX() - fN*sumx;
     Double_t y = nucleon->GetY() - fN*sumy;
     Double_t z = nucleon->GetZ() - fN*sumz;
     nucleon->SetXYZ(x,y,z);
   } else if ((fRecenter==3)||(fRecenter==4)) {
     TVector3 zVec;
     zVec.SetXYZ(0,0,1);
     TVector3 shiftVec;
     shiftVec.SetXYZ(sumx,sumy,sumz);
     TVector3 orthVec;
     orthVec = shiftVec.Cross(zVec);
     TRotation myRot;
     myRot.Rotate(shiftVec.Angle(zVec),orthVec);
     TVector3 myNuc;
     for (Int_t i = 0; i<fN; ++i) {
       TGlauNucleon *nucleon=(TGlauNucleon*)(fNucleons->At(i));
       myNuc.SetXYZ(nucleon->GetX(),nucleon->GetY(),nucleon->GetZ());
       myNuc.Transform(myRot);
       nucleon->SetXYZ(myNuc.X(), myNuc.Y(), myNuc.Z());
     }
     if (fRecenter==3)
       fsumz = shiftVec.Mag();
   }
 
   // recenter and shift
   for (Int_t i = 0; i<fN; ++i) {
     TGlauNucleon *nucleon=(TGlauNucleon*)(fNucleons->At(i));
     nucleon->SetXYZ(nucleon->GetX()-fsumx + xshift,
 		    nucleon->GetY()-fsumy,
 		    nucleon->GetZ()-fsumz);
   }
 
   return finalShift;
 }
 
 //---------------------------------------------------------------------------------
   ClassImp(TGlauberMC)
   ClassImp(TGlauberMC::Event)
 //---------------------------------------------------------------------------------
 
 TGlauberMC::TGlauberMC(const char* NA, const char* NB, Double_t xsect, Double_t xsectsigma) :
   fANucleus(NA),fBNucleus(NB),
   fXSect(xsect),fXSectOmega(0),fXSectLambda(0),fXSectEvent(0),
   fNucleonsA(0),fNucleonsB(0),fNucleons(0),
   fAN(0),fBN(0),fNt(0),
   fEvents(0),fTotalEvents(0),fBmin(0),fBmax(20),fHardFrac(0.65),
   fDetail(99),fCalcArea(0),fCalcLength(0), fDoCore(0),
   fMaxNpartFound(0),f2Cx(0),fPTot(0),fNNProf(0),
   fEv()
 {
   if (xsectsigma>0) {
     fXSectOmega = xsectsigma;
     fXSectLambda = 1;
     fPTot = new TF1("fPTot","((x/[2])/(x/[2]+[0]))*exp(-(((x/[2])/[0]-1 )**2)/([1]*[1]))/[2]",0,300);
     fPTot->SetParameters(fXSect,fXSectOmega,fXSectLambda);
     fPTot->SetNpx(1000);
     fXSectLambda = fXSect/fPTot->GetHistogram()->GetMean();
     cout << "final lambda=" << fXSectLambda << endl;
     fPTot->SetParameters(fXSect,fXSectOmega,fXSectLambda);
     cout << "final <sigma>=" << fPTot->GetHistogram()->GetMean() << endl;
   }
 
   TString name(Form("Glauber_%s_%s",fANucleus.GetName(),fBNucleus.GetName()));
   TString title(Form("Glauber %s+%s Version",fANucleus.GetName(),fBNucleus.GetName()));
   SetName(name);
   SetTitle(title);
 }
 
 Bool_t TGlauberMC::CalcEvent(Double_t bgen)
 {
   // calc next event
   if (!fNucleonsA) {
     fNucleonsA = fANucleus.GetNucleons();
     fAN = fANucleus.GetN();
     for (Int_t i = 0; i<fAN; ++i) {
       TGlauNucleon *nucleonA=(TGlauNucleon*)(fNucleonsA->At(i));
       nucleonA->SetInNucleusA();
     }
   }
   if (!fNucleonsB) {
     fNucleonsB = fBNucleus.GetNucleons();
     fBN = fBNucleus.GetN();
     for (Int_t i = 0; i<fBN; ++i) {
       TGlauNucleon *nucleonB=(TGlauNucleon*)(fNucleonsB->At(i));
       nucleonB->SetInNucleusB();
     }
   }
 
   if (fPTot)
     fXSectEvent = fPTot->GetRandom();
   else 
     fXSectEvent = fXSect;
 
   // "ball" diameter = distance at which two balls interact
   Double_t d2 = (Double_t)fXSectEvent/(TMath::Pi()*10); // in fm^2
   Double_t bh = TMath::Sqrt(d2*fHardFrac);
   if (fNNProf) {
     Double_t xmin=0,xmax=0;
     fNNProf->GetRange(xmin,xmax);
     d2 = xmax*xmax;
   }
 
   fEv.Reset();
   memset(fBC,0,sizeof(Bool_t)*999*999);
   Int_t nc=0,nh=0;
   for (Int_t i = 0; i<fBN; ++i) {
     TGlauNucleon *nucleonB=(TGlauNucleon*)(fNucleonsB->At(i));
     Bool_t tB=nucleonB->GetType();
     for (Int_t j = 0; j<fAN; ++j) {
       TGlauNucleon *nucleonA=(TGlauNucleon*)(fNucleonsA->At(j));
       Double_t dx = nucleonB->GetX()-nucleonA->GetX();
       Double_t dy = nucleonB->GetY()-nucleonA->GetY();
       Double_t dij = dx*dx+dy*dy;
       if (dij>d2) 
         continue;
       Double_t bij = TMath::Sqrt(dij);
       if (fNNProf) {
         Double_t val = fNNProf->Eval(bij);
         Double_t ran = gRandom->Uniform();
         if (ran>val)
           continue;
       }
       nucleonB->Collide();
       nucleonA->Collide();
       fBC[i][j] = 1;
       fEv.BNN  += bij;
       ++nc;
       if (bij<bh)
         ++nh;
       Bool_t tA=nucleonA->GetType();
       if (tA!=tB)
         ++fEv.Ncollpn;
       else if (tA==1)
         ++fEv.Ncollpp;
       else
         ++fEv.Ncollnn;
       if (nc==1) {
         fEv.X0 = (nucleonA->GetX()+nucleonB->GetX())/2;
         fEv.Y0 = (nucleonA->GetY()+nucleonB->GetY())/2;
       }
     }
   }
   fEv.B = bgen;
   ++fTotalEvents;
   if (nc>0) {
     ++fEvents;
     fEv.Ncoll     = nc;
     fEv.Nhard     = nh;
     fEv.BNN      /= nc;
     return CalcResults(bgen);
   }
   return kFALSE;
 }
 
 Bool_t TGlauberMC::CalcResults(Double_t bgen)
 {
   // calc results for the given event
   Double_t sumW=0;
   Double_t sumWA=0;
   Double_t sumWB=0;
 
   Double_t sinphi[10] = {0};
   Double_t cosphi[10] = {0};
   Double_t rn[10]     = {0};
 
   const Int_t kNc = fDoCore; // used later for core/corona
 
   for (Int_t i = 0; i<fAN; ++i) {
     TGlauNucleon *nucleonA=(TGlauNucleon*)(fNucleonsA->At(i));
     Double_t xA=nucleonA->GetX();
     Double_t yA=nucleonA->GetY();
     fEv.MeanXSystem  += xA;
     fEv.MeanYSystem  += yA;
     fEv.MeanXA  += xA;
     fEv.MeanYA  += yA;
     if (nucleonA->IsWounded()) {
       Double_t w = nucleonA->Get2CWeight(f2Cx);
       ++fEv.Npart;
       if (nucleonA->GetNColl()==1)
 	++fEv.Npart0;
       ++fEv.NpartA;
       sumW   += w;
       sumWA  += w;
       fEv.MeanX  += xA * w;
       fEv.MeanY  += yA * w;
       fEv.MeanX2 += xA * xA * w;
       fEv.MeanY2 += yA * yA * w;
       fEv.MeanXY += xA * yA * w;
     }
   }
 
   for (Int_t i = 0; i<fBN; ++i) {
     TGlauNucleon *nucleonB=(TGlauNucleon*)(fNucleonsB->At(i));
     Double_t xB=nucleonB->GetX();
     Double_t yB=nucleonB->GetY();
     fEv.MeanXSystem  += xB;
     fEv.MeanYSystem  += yB;
     fEv.MeanXB  += xB;
     fEv.MeanYB  += yB;
     if (nucleonB->IsWounded()) {
       Double_t w = nucleonB->Get2CWeight(f2Cx);
       ++fEv.Npart;
       if (nucleonB->GetNColl()==1)
 	++fEv.Npart0;
       ++fEv.NpartB;
       sumW   += w;
       sumWB  += w;
       fEv.MeanX  += xB * w;
       fEv.MeanY  += yB * w;
       fEv.MeanX2 += xB * xB * w;
       fEv.MeanY2 += yB * yB * w;
       fEv.MeanXY += xB * yB * w;
     }
   }
   if (fEv.Npart>0) {
     fEv.MeanX  /= sumW;
     fEv.MeanY  /= sumW;
     fEv.MeanX2 /= sumW;
     fEv.MeanY2 /= sumW;
     fEv.MeanXY /= sumW;
   } else {
     fEv.MeanX = 0;
     fEv.MeanY  = 0;
     fEv.MeanX2 = 0;
     fEv.MeanY2 = 0;
     fEv.MeanXY = 0;
   }
 
   if (fAN+fBN>0) {
     fEv.MeanXSystem /= (fAN + fBN);
     fEv.MeanYSystem /= (fAN + fBN);
   } else {
     fEv.MeanXSystem = 0;
     fEv.MeanYSystem = 0;
   }
   if (fAN>0) {
     fEv.MeanXA /= fAN;
     fEv.MeanYA /= fAN;
   } else {
     fEv.MeanXA = 0;
     fEv.MeanYA = 0;
   }
   if (fBN>0) {
     fEv.MeanXB /= fBN;
     fEv.MeanYB /= fBN;
   } else {
     fEv.MeanXB = 0;
     fEv.MeanYB = 0;
   }
 
   fEv.VarX  = fEv.MeanX2-(fEv.MeanX*fEv.MeanX);
   fEv.VarY  = fEv.MeanY2-(fEv.MeanY*fEv.MeanY);
   fEv.VarXY = fEv.MeanXY-fEv.MeanX*fEv.MeanY;
   Double_t tmpa = fEv.VarX*fEv.VarY-fEv.VarXY*fEv.VarXY;
   if (tmpa<0) 
     fEv.AreaW = -1;
   else 
     fEv.AreaW = TMath::Sqrt(tmpa);
 
   if (fEv.Npart>0) {
     // do full moments relative to meanX and meanY
     for (Int_t n = 1; n<10; ++n) {
       for (Int_t ia = 0; ia<fAN; ++ia) {
         TGlauNucleon *nucleonA=(TGlauNucleon*)(fNucleonsA->At(ia));
 	if (nucleonA->GetNColl()<=kNc) 
 	  continue;
 	Double_t xA=nucleonA->GetX() - fEv.MeanX;
 	Double_t yA=nucleonA->GetY() - fEv.MeanY;
 	Double_t r = TMath::Sqrt(xA*xA+yA*yA);
 	Double_t phi = TMath::ATan2(yA,xA);
 	Double_t w = n;
 	if (n==1) 
 	  w = 3; // use r^3 weighting for Ecc1/Psi1
 	Double_t rw = TMath::Power(r,w);
 	cosphi[n] += rw*TMath::Cos(n*phi);
 	sinphi[n] += rw*TMath::Sin(n*phi);
 	rn[n] += rw;
       }
       for (Int_t ib = 0; ib<fBN; ++ib) {
         TGlauNucleon *nucleonB=(TGlauNucleon*)(fNucleonsB->At(ib));
 	if (nucleonB->GetNColl()<=kNc) 
 	  continue;
 	Double_t xB=nucleonB->GetX() - fEv.MeanX;
 	Double_t yB=nucleonB->GetY() - fEv.MeanY;
 	Double_t r = TMath::Sqrt(xB*xB+yB*yB);
 	Double_t phi = TMath::ATan2(yB,xB);
 	Double_t w = n;
 	if (n==1)
 	  w = 3; // use r^3 weighting for Ecc1/Psi1
 	Double_t rw = TMath::Power(r,w);
 	cosphi[n] += rw*TMath::Cos(n*phi);
 	sinphi[n] += rw*TMath::Sin(n*phi);
 	rn[n] += rw;
       }
       cosphi[n] /= fEv.Npart;
       sinphi[n] /= fEv.Npart;
       rn[n] /= fEv.Npart;
       if (rn[n]>0) {
 	fPsiN[n] = (TMath::ATan2(sinphi[n],cosphi[n]) + TMath::Pi())/n;
 	fEccN[n] = TMath::Sqrt(sinphi[n]*sinphi[n]+cosphi[n]*cosphi[n])/rn[n];
       } else {
 	fPsiN[n] = -1;
 	fEccN[n] = -1;
       }
     }
     if (!kNc) { //silly test but useful to catch errors 
       Double_t t=TMath::Sqrt(TMath::Power(fEv.VarY-fEv.VarX,2)+4.*fEv.VarXY*fEv.VarXY)/(fEv.VarY+fEv.VarX)/fEccN[2];
       if (t<0.99||t>1.01)
         cout << "Error: Expected t=1 but found t=" << t << endl;
     }
   }
 
   fEv.B      = bgen;
   fEv.PhiA   = fANucleus.GetPhiRot();
   fEv.ThetaA = fANucleus.GetThetaRot();
   fEv.PhiB   = fBNucleus.GetPhiRot();
   fEv.ThetaB = fBNucleus.GetThetaRot();
   fEv.Psi1   = fPsiN[1];
   fEv.Ecc1   = fEccN[1];
   fEv.Psi2   = fPsiN[2];
   fEv.Ecc2   = fEccN[2];
   fEv.Psi3   = fPsiN[3];
   fEv.Ecc3   = fEccN[3];
   fEv.Psi4   = fPsiN[4];
   fEv.Ecc4   = fEccN[4];
   fEv.Psi5   = fPsiN[5];
   fEv.Ecc5   = fEccN[5];
 
   if (fCalcArea) {
     const Int_t nbins=200;
     const Double_t ell=10;
     const Double_t da=2*ell*2*ell/nbins/nbins;
     const Double_t d2 = (Double_t)fXSectEvent/(TMath::Pi()*10); // in fm^2
     const Double_t r2 = d2/4.;
     const Double_t mx = fEv.MeanX;
     const Double_t my = fEv.MeanY;
     TH2D areaA("hAreaA",";x (fm);y (fm)",nbins,-ell,ell,nbins,-ell,ell);
     TH2D areaB("hAreaB",";x (fm);y (fm)",nbins,-ell,ell,nbins,-ell,ell);
     for (Int_t i = 0; i<fAN; ++i) {
       TGlauNucleon *nucleonA=(TGlauNucleon*)(fNucleonsA->At(i));
       if (!nucleonA->IsWounded())
         continue;
       if (nucleonA->GetNColl()==kNc)
         continue;
       Double_t x = nucleonA->GetX()-mx;
       Double_t y = nucleonA->GetY()-my;
       for (Int_t xi=1; xi<=nbins; ++xi) {
         for (Int_t yi=1; yi<=nbins; ++yi) {
           Int_t bin = areaA.GetBin(xi,yi);
           Double_t val=areaA.GetBinContent(bin);
           if (val>0)
             continue;
           Double_t dx=x-areaA.GetXaxis()->GetBinCenter(xi);
           Double_t dy=y-areaA.GetYaxis()->GetBinCenter(yi);
           if (dx*dx+dy*dy<r2)
             areaA.SetBinContent(bin,1);
         }
       }
     }
     for (Int_t i = 0; i<fBN; ++i) {
       TGlauNucleon *nucleonB=(TGlauNucleon*)(fNucleonsB->At(i));
       if (!nucleonB->IsWounded())
         continue;
       if (nucleonB->GetNColl()==kNc)
         continue;
       Double_t x = nucleonB->GetX()-mx;
       Double_t y = nucleonB->GetY()-my;
       for (Int_t xi=1; xi<=nbins; ++xi) {
         for (Int_t yi=1; yi<=nbins; ++yi) {
           Int_t bin = areaB.GetBin(xi,yi);
           Double_t val=areaB.GetBinContent(bin);
           if (val>0)
             continue;
           Double_t dx=x-areaB.GetXaxis()->GetBinCenter(xi);
           Double_t dy=y-areaB.GetYaxis()->GetBinCenter(yi);
           if (dx*dx+dy*dy<r2)
             areaB.SetBinContent(bin,1);
         }
       }
     }
     Double_t overlap1=0;
     Double_t overlap2=0;
     for (Int_t xi=1; xi<=nbins; ++xi) {
       for (Int_t yi=1; yi<=nbins; ++yi) {
         Int_t bin = areaA.GetBin(xi,yi);
         Double_t vA=areaA.GetBinContent(bin);
         Double_t vB=areaB.GetBinContent(bin);
         if (vA>0&&vB>0)
           ++overlap1;
         if (vA>0||vB>0)
           ++overlap2;
       }
     }
     fEv.AreaO = overlap1*da;
     fEv.AreaA = overlap2*da;
   }
 
   if (fCalcLength) {
     const Double_t krhs = TMath::Sqrt(fXSectEvent/40./TMath::Pi());
     const Double_t ksg  = krhs/TMath::Sqrt(5);
     const Double_t kDL  = 0.1;
     TF1 rad("rad","2*pi/[0]/[0]*TMath::Exp(-x*x/(2.*[0]*[0]))",0.0,5*ksg); 
     rad.SetParameter(0,ksg);
     const Double_t minval = rad.Eval(5*ksg);
     fEv.Phi0         = gRandom->Uniform(0,TMath::TwoPi());
     Double_t kcphi0  = TMath::Cos(fEv.Phi0);
     Double_t ksphi0  = TMath::Sin(fEv.Phi0);
     Double_t x       = fEv.X0;
     Double_t y       = fEv.Y0;
     Double_t i0a     = 0;
     Double_t i1a     = 0;
     Double_t l       = 0;
     Double_t val     = CalcDens(rad,x,y);
     while (val>minval) {
       x     += kDL * kcphi0;
       y     += kDL * ksphi0;
       i0a   += val;
       i1a   += l*val;
       l+=kDL;
       val    = CalcDens(rad,x,y);
     }
     fEv.Length = 2*i1a/i0a;
   }
 
   if (fEv.Npart > fMaxNpartFound) 
     fMaxNpartFound = fEv.Npart;
 
   return kTRUE;
 }
 
 Double_t TGlauberMC::CalcDens(TF1 &prof, Double_t xval, Double_t yval) const
 {
   Double_t rmin=0,rmax=0;
   prof.GetRange(rmin,rmax);
   Double_t r2max = rmax*rmax;
   Double_t ret = 0;
   for (Int_t i = 0; i<fAN; ++i) {
     TGlauNucleon *nucleonA=(TGlauNucleon*)(fNucleonsA->At(i));
     if (!nucleonA->IsWounded())
       continue;
     Double_t x = nucleonA->GetX();
     Double_t y = nucleonA->GetY();
     Double_t r2=(xval-x)*(xval-x)+(yval-y)*(yval-y);
     if (r2>r2max)
       continue;
     ret += prof.Eval(TMath::Sqrt(r2));
   }
   for (Int_t i = 0; i<fBN; ++i) {
     TGlauNucleon *nucleonB=(TGlauNucleon*)(fNucleonsB->At(i));
     if (!nucleonB->IsWounded())
       continue;
     Double_t x = nucleonB->GetX();
     Double_t y = nucleonB->GetY();
     Double_t r2=(xval-x)*(xval-x)+(yval-y)*(yval-y);
     if (r2>r2max)
       continue;
     ret += prof.Eval(TMath::Sqrt(r2));
   }
   return ret;
 }
 
 void TGlauberMC::Draw(Option_t* option)
 {
   static TH2F *h2f = new TH2F("hGlauberMC",";x (fm);y(fm)",1,-18,18,1,-12,12);
 
   h2f->Reset();
   h2f->SetStats(0);
   h2f->Draw();
 
   TEllipse e;
   e.SetFillColor(0);
   e.SetFillStyle(0);
   e.SetLineColor(1);
   e.SetLineStyle(2);
   e.SetLineWidth(1);
   e.DrawEllipse(GetB()/2,0,fBNucleus.GetR(),fBNucleus.GetR(),0,360,0);
   e.DrawEllipse(-GetB()/2,0,fANucleus.GetR(),fANucleus.GetR(),0,360,0);
   fANucleus.Draw(fXSect, kMagenta, kYellow);
   fBNucleus.Draw(fXSect, kMagenta, kOrange);
 
   TString opt(option);
   if (opt.IsNull())
     return;
 
   Double_t sy2 = GetSy2();
   Double_t sx2 = GetSx2();
   Double_t phase = 0;
   if (sy2<sx2) {
     Double_t d = sx2;
     sx2 = sy2;
     sy2 = d;
     phase = TMath::Pi()/2.;
   }
   Double_t x1 = (0.5*(sy2-sx2)+TMath::Sqrt(TMath::Power(sy2-sx2,2.)-4*TMath::Power(GetSxy(),2)));
   Double_t ang = TMath::ATan2(-GetSxy(),x1)+phase;
   TLine l;
   l.SetLineWidth(3);
   l.DrawLine(-10*TMath::Cos(ang),-10*TMath::Sin(ang),10*TMath::Cos(ang),10*TMath::Sin(ang));
 }
 
 Double_t TGlauberMC::GetTotXSect() const
 {
   return (1.*fEvents/fTotalEvents)*TMath::Pi()*fBmax*fBmax/100;
 }
 
 Double_t TGlauberMC::GetTotXSectErr() const
 {
   return GetTotXSect()/TMath::Sqrt((Double_t)fEvents) * TMath::Sqrt(Double_t(1.-fEvents/fTotalEvents));
 }
 
 TObjArray *TGlauberMC::GetNucleons() 
 {
   if (!fNucleonsA || !fNucleonsB) return 0;
   if (fNucleons) return fNucleons;
 
   fNucleonsA->SetOwner(0);
   fNucleonsB->SetOwner(0);
   TObjArray *allnucleons=new TObjArray(fAN+fBN);
   allnucleons->SetOwner();
   for (Int_t i = 0; i<fAN; ++i) {
     allnucleons->Add(fNucleonsA->At(i));
   }
   for (Int_t i = 0; i<fBN; ++i) {
     allnucleons->Add(fNucleonsB->At(i));
   }
   fNucleons = allnucleons;
   return allnucleons;
 }
 
 Bool_t TGlauberMC::NextEvent(Double_t bgen)
 {
   if (bgen<0) 
     bgen = TMath::Sqrt((fBmax*fBmax-fBmin*fBmin)*gRandom->Rndm()+fBmin*fBmin);
 
   fANucleus.ThrowNucleons(-bgen/2.);
   fBNucleus.ThrowNucleons(bgen/2.);
 
   return CalcEvent(bgen);
 }
 
 Bool_t TGlauberMC::ReadNextEvent(Bool_t calc, const char *fname)
 {
   static TFile *inf = 0;
   static Int_t iev  = 0;
   if (fname) {
     cout << "ReadNextEvent: Setting up file " << fname << endl;
     delete inf;
     inf = TFile::Open(fname);
     if (!inf) 
       return 0;
     if (!fNucleonsA) {
       fANucleus.ThrowNucleons();
       fNucleonsA = fANucleus.GetNucleons();
       fAN = fANucleus.GetN();
       for (Int_t i = 0; i<fAN; ++i) {
 	TGlauNucleon *nucleonA=(TGlauNucleon*)(fNucleonsA->At(i));
 	nucleonA->SetInNucleusA();
       }
     }
     if (!fNucleonsB) {
       fBNucleus.ThrowNucleons();
       fNucleonsB = fBNucleus.GetNucleons();
       fBN = fBNucleus.GetN();
       for (Int_t i = 0; i<fBN; ++i) {
 	TGlauNucleon *nucleonB=(TGlauNucleon*)(fNucleonsB->At(i));
 	nucleonB->SetInNucleusB();
       }
     }
     if (calc)
       return 1;
     fNt = dynamic_cast<TNtuple*>(inf->Get(Form("nt_%s_%s",fANucleus.GetName(),fBNucleus.GetName())));
     if (!fNt) {
       cerr << "ReadNextEvent: Could not find ntuple!" << endl;
       inf->ls();
       return 0;
     }
     fNt->SetBranchAddress("Npart",&fEv.Npart);
     fNt->SetBranchAddress("Ncoll",&fEv.Ncoll);
     fNt->SetBranchAddress("B",&fEv.B);
     fNt->SetBranchAddress("BNN",&fEv.BNN);
     fNt->SetBranchAddress("VarX",&fEv.VarX);
     fNt->SetBranchAddress("VarY",&fEv.VarY);
     fNt->SetBranchAddress("VarXY",&fEv.VarXY);
     fNt->SetBranchAddress("NpartA",&fEv.NpartA);
     fNt->SetBranchAddress("NpartB",&fEv.NpartB);
     fNt->SetBranchAddress("Npart0",&fEv.Npart0);
     fNt->SetBranchAddress("Psi1",&fEv.Psi1);
     fNt->SetBranchAddress("Ecc1",&fEv.Ecc1);
     fNt->SetBranchAddress("Psi2",&fEv.Psi2);
     fNt->SetBranchAddress("Ecc2",&fEv.Ecc2);
     fNt->SetBranchAddress("Psi3",&fEv.Psi3);
     fNt->SetBranchAddress("Ecc3",&fEv.Ecc3);
     fNt->SetBranchAddress("Psi4",&fEv.Psi4);
     fNt->SetBranchAddress("Ecc4",&fEv.Ecc4);
     fNt->SetBranchAddress("Psi5",&fEv.Psi5);
     fNt->SetBranchAddress("Ecc5",&fEv.Ecc5);
     return 1;
   }
   if ((!inf)||(!fNt&&!calc)) {
     cerr << "ReadNextEvent was not initialized" <<endl;
     return 0;
   }
   TObjArray *arr = dynamic_cast<TObjArray*>(inf->Get(Form("nucleonarray%d",iev)));
   if (!arr) {
     if (iev==0) {
       cerr << "ReadNextEvent could not read nucleon array for event " << iev << endl;
       return 0;
     }
     iev = 0;
     cerr << "ReadNextEvent resetting to first event" << endl;
     arr = dynamic_cast<TObjArray*>(inf->Get(Form("nucleonarray%d",iev)));
   }
 
   Double_t bgenA=0, bgenB=0;
   Int_t inA=0, inB=0;
   const Int_t nNucls = arr->GetEntries();
   for (Int_t iNucl=0; iNucl<nNucls; ++iNucl) {
     TGlauNucleon *nuclinp = static_cast<TGlauNucleon*>(arr->At(iNucl));
     TGlauNucleon *nuclout = 0;
     if (nuclinp->IsInNucleusB()) { 
       nuclout = static_cast<TGlauNucleon*>(fNucleonsB->At(inB));
       bgenB += nuclinp->GetX();
       ++inB;
     } else {
       nuclout = static_cast<TGlauNucleon*>(fNucleonsA->At(inA));
       bgenA += nuclinp->GetX();
       ++inA;
     }
     nuclout->Reset();
     nuclout->SetXYZ(nuclinp->GetX(),nuclinp->GetY(),nuclinp->GetZ());
     nuclout->SetType(nuclinp->GetType());
     nuclout->SetEnergy(nuclinp->GetEnergy());
     if (!calc)
       nuclout->SetNColl(nuclinp->GetNColl());
   }
   delete arr;
   Double_t bgen = bgenB/inB-bgenA/inA;
   if (calc) {
     Bool_t ret = CalcEvent(bgen);
     if (0) 
       cout << iev << ": " << fEv.B << " " << fEv.Npart << " " << fEv.Ncoll << " " << fEv.Npart0 << endl;
     ++iev;
     return ret;
   }
   Int_t ret = fNt->GetEntry(iev);
   if (ret<=0) 
     return 0;
   fEccN[1]=fEv.Ecc1;
   fEccN[2]=fEv.Ecc2;
   fEccN[3]=fEv.Ecc3;
   fEccN[4]=fEv.Ecc4;
   fEccN[5]=fEv.Ecc5;
   if (0) 
     cout << iev << ": " << fEv.B << " " << fEv.Npart << " " << fEv.Ncoll << " " << fEv.Npart0 << endl;
   if (0) { // test ntuple values vs re-calculated values
     Double_t npart = fEv.Npart;
     Double_t ncoll = fEv.Ncoll;
     Double_t ecc2  = fEv.Ecc2;
     CalcEvent(bgen);
     if (npart!=fEv.Npart) 
       cout << iev << " differ in npart " << npart << " " << fEv.Npart << endl;
     if (ncoll!=fEv.Ncoll) 
       cout << iev << " differ in ncoll " << ncoll << " " << fEv.Ncoll << endl;
     if (TMath::Abs(ecc2-fEv.Ecc2)>0.001) 
       cout << iev << " differ in ecc2 " << ecc2 << " " << fEv.Ecc2 << endl;
   }
   ++iev;
   return 1;
 }
 
 void TGlauberMC::Run(Int_t nevents, Double_t b)
 {
   if (fNt == 0) {
     TString name(Form("nt_%s_%s",fANucleus.GetName(),fBNucleus.GetName()));
     TString title(Form("%s + %s (x-sect = %.1f mb) str %s",fANucleus.GetName(),fBNucleus.GetName(),fXSect,Str()));
     TString vars("Npart:Ncoll:Nhard:B:BNN:Ncollpp:Ncollpn:Ncollnn:VarX:VarY:VarXY:NpartA:NpartB:Npart0:AreaW");
     if (fDetail>1)
       vars+=":Psi1:Ecc1:Psi2:Ecc2:Psi3:Ecc3:Psi4:Ecc4:Psi5:Ecc5";
     if (fDetail>2)
       vars+=":AreaO:AreaA:X0:Y0:Phi0:Length";
     if (fDetail>3)
       vars+=":MeanX:MeanY:MeanX2:MeanY2:MeanXY:MeanXSystem:MeanYSystem:MeanXA:MeanYA:MeanXB:MeanYB";
     if (fDetail>4)
       vars+=":PhiA:ThetaA:PhiB:ThetaB";
     fNt = new TNtuple(name,title,vars);
     fNt->SetDirectory(0);
     TObjArray *l = fNt->GetListOfBranches();
     for (Int_t i=0; i<l->GetEntries(); ++i) {
       TBranch *br = dynamic_cast<TBranch*>(l->At(i));
       if (br)
         br->SetCompressionLevel(9);
     }
   }
 
   for (Int_t i = 0; i<nevents; ++i) {
     while (!NextEvent(b)) {}
     fNt->Fill((Float_t*)(&fEv.Npart));
     if ((i>0)&&(i%100)==0) 
       cout << "Event # " << i << " x-sect = " << GetTotXSect() << " +- " << GetTotXSectErr() << " b        \r" << flush;
   }
   if (nevents>99)
     cout << endl << "Done!" << endl;
 }
 #endif