From 3dc8cf84015ec89d02df5b7b7dd4ad09062a12d4 Mon Sep 17 00:00:00 2001
From: James William Monk <james.william.monk@cern.ch>
Date: Wed, 27 Nov 2013 15:51:06 +0100
Subject: [PATCH] tagging for Pythia 8.180 compatibility
 (Pythia8_i-00-09-10-01)

---
 Generators/Pythia8_i/Pythia8_i/Pythia8_i.h    | 129 +++++
 .../Pythia8_i/Pythia8_i/UserHooksFactory.h    |  69 +++
 .../Pythia8_i/Pythia8_i/UserProcessFactory.h  |  70 +++
 .../Pythia8_i/UserResonanceFactory.h          |  72 +++
 Generators/Pythia8_i/cmt/requirements         |  35 ++
 .../Pythia8_i/share/Powheg.ZMu.MC11.events    | 208 ++++++++
 .../Pythia8_i/share/enhanceMPI_example.py     |  12 +
 .../Pythia8_i/share/jobOptions.pythia8.py     |  12 +
 Generators/Pythia8_i/share/lhef_example.py    |  32 ++
 .../Pythia8_i/share/qcdVetoedShowerExample.py |  36 ++
 .../Pythia8_i/share/suppressMPI_example.py    |  12 +
 .../Pythia8_i/share/userProcess_example.py    |  36 ++
 .../Pythia8_i/share/vetoedISR_example.py      |  35 ++
 Generators/Pythia8_i/src/Pythia8_i.cxx        | 410 ++++++++++++++
 .../Pythia8_i/src/UserHooks/EnhanceMPI.cxx    | 104 ++++
 .../Pythia8_i/src/UserHooks/GravFlat.cxx      | 117 ++++
 .../src/UserHooks/ISRVetoedShower.cxx         | 173 ++++++
 .../src/UserHooks/PTRelVetoedShower.cxx       | 219 ++++++++
 .../src/UserHooks/PoWHEGVetoedShower.cxx      | 180 +++++++
 .../src/UserHooks/QCDVetoedShower.cxx         | 138 +++++
 .../Pythia8_i/src/UserHooks/SuppressMPI.cxx   |  85 +++
 .../Pythia8_i/src/UserHooks/UserHooksUtils.h  | 116 ++++
 .../Pythia8_i/src/UserHooks/VetoedShower.cxx  | 151 ++++++
 .../src/UserHooks/WZVetoedShower.cxx          | 128 +++++
 .../Pythia8_i/src/UserHooks/WprimeFlat.cxx    |  60 +++
 .../Pythia8_i/src/UserHooks/WprimeWZFlat.cxx  |  68 +++
 Generators/Pythia8_i/src/UserHooks/main31.cxx | 505 ++++++++++++++++++
 Generators/Pythia8_i/src/UserHooksFactory.cxx |  27 +
 .../Pythia8_i/src/UserProcessFactory.cxx      |  28 +
 .../src/UserProcesses/Sigma2qqbar2emu.cxx     | 127 +++++
 .../UserProcesses/Sigma2qqbar2lStarlBar.cxx   | 187 +++++++
 .../Sigma2qqbar2lStarlStarBar.cxx             | 186 +++++++
 .../Pythia8_i/src/UserResonanceFactory.cxx    |  33 ++
 .../src/UserResonances/ResonanceExcitedCI.cxx | 114 ++++
 .../src/components/Pythia8_i_entries.cxx      |  11 +
 .../src/components/Pythia8_i_load.cxx         |   7 +
 36 files changed, 3932 insertions(+)
 create mode 100644 Generators/Pythia8_i/Pythia8_i/Pythia8_i.h
 create mode 100644 Generators/Pythia8_i/Pythia8_i/UserHooksFactory.h
 create mode 100644 Generators/Pythia8_i/Pythia8_i/UserProcessFactory.h
 create mode 100644 Generators/Pythia8_i/Pythia8_i/UserResonanceFactory.h
 create mode 100644 Generators/Pythia8_i/cmt/requirements
 create mode 100644 Generators/Pythia8_i/share/Powheg.ZMu.MC11.events
 create mode 100644 Generators/Pythia8_i/share/enhanceMPI_example.py
 create mode 100644 Generators/Pythia8_i/share/jobOptions.pythia8.py
 create mode 100644 Generators/Pythia8_i/share/lhef_example.py
 create mode 100644 Generators/Pythia8_i/share/qcdVetoedShowerExample.py
 create mode 100644 Generators/Pythia8_i/share/suppressMPI_example.py
 create mode 100644 Generators/Pythia8_i/share/userProcess_example.py
 create mode 100644 Generators/Pythia8_i/share/vetoedISR_example.py
 create mode 100644 Generators/Pythia8_i/src/Pythia8_i.cxx
 create mode 100644 Generators/Pythia8_i/src/UserHooks/EnhanceMPI.cxx
 create mode 100644 Generators/Pythia8_i/src/UserHooks/GravFlat.cxx
 create mode 100644 Generators/Pythia8_i/src/UserHooks/ISRVetoedShower.cxx
 create mode 100644 Generators/Pythia8_i/src/UserHooks/PTRelVetoedShower.cxx
 create mode 100644 Generators/Pythia8_i/src/UserHooks/PoWHEGVetoedShower.cxx
 create mode 100644 Generators/Pythia8_i/src/UserHooks/QCDVetoedShower.cxx
 create mode 100644 Generators/Pythia8_i/src/UserHooks/SuppressMPI.cxx
 create mode 100644 Generators/Pythia8_i/src/UserHooks/UserHooksUtils.h
 create mode 100644 Generators/Pythia8_i/src/UserHooks/VetoedShower.cxx
 create mode 100644 Generators/Pythia8_i/src/UserHooks/WZVetoedShower.cxx
 create mode 100644 Generators/Pythia8_i/src/UserHooks/WprimeFlat.cxx
 create mode 100644 Generators/Pythia8_i/src/UserHooks/WprimeWZFlat.cxx
 create mode 100644 Generators/Pythia8_i/src/UserHooks/main31.cxx
 create mode 100644 Generators/Pythia8_i/src/UserHooksFactory.cxx
 create mode 100644 Generators/Pythia8_i/src/UserProcessFactory.cxx
 create mode 100644 Generators/Pythia8_i/src/UserProcesses/Sigma2qqbar2emu.cxx
 create mode 100644 Generators/Pythia8_i/src/UserProcesses/Sigma2qqbar2lStarlBar.cxx
 create mode 100644 Generators/Pythia8_i/src/UserProcesses/Sigma2qqbar2lStarlStarBar.cxx
 create mode 100644 Generators/Pythia8_i/src/UserResonanceFactory.cxx
 create mode 100644 Generators/Pythia8_i/src/UserResonances/ResonanceExcitedCI.cxx
 create mode 100644 Generators/Pythia8_i/src/components/Pythia8_i_entries.cxx
 create mode 100644 Generators/Pythia8_i/src/components/Pythia8_i_load.cxx

diff --git a/Generators/Pythia8_i/Pythia8_i/Pythia8_i.h b/Generators/Pythia8_i/Pythia8_i/Pythia8_i.h
new file mode 100644
index 00000000000..6fadee22fc9
--- /dev/null
+++ b/Generators/Pythia8_i/Pythia8_i/Pythia8_i.h
@@ -0,0 +1,129 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef GENERATOR_PYTHIA8_H
+#define GENERATOR_PYTHIA8_H
+
+#include "GeneratorModules/GenModule.h"
+
+#include "Pythia8/Pythia.h"
+#include "Pythia8/Pythia8ToHepMC.h"
+
+// calls to fortran routines
+#include "CLHEP/Random/RandFlat.h"
+#include "AthenaKernel/IAtRndmGenSvc.h"
+
+
+/**
+ *  Author: James Monk (jmonk@hep.ucl.ac.uk)
+*/
+
+using std::string;
+
+class IAtRndmGenSvc;
+
+namespace Pythia8{
+  class Sigma2Process;
+}
+
+
+class customRndm : public Pythia8::RndmEngine {
+public:
+  
+  // Constructor.
+  customRndm():
+    m_engine(0), m_RndmGenSvc(0) {}
+  
+  // Routine for generating a random number.
+  inline double flat(){    
+    m_engine=m_RndmGenSvc->GetEngine(m_stream);
+    return CLHEP::RandFlat::shoot(m_engine);
+  };
+  
+  // Initialisation Routine 
+  inline void init(IAtRndmGenSvc &RndmGenSvc, std::string RndmStream){m_RndmGenSvc=&RndmGenSvc; m_stream=RndmStream;};
+  std::string m_stream; 
+  
+private:
+  CLHEP::HepRandomEngine* m_engine;
+  IAtRndmGenSvc* m_RndmGenSvc;
+};
+
+
+//namespace Generator{
+class Pythia8_i: public GenModule{
+
+public:
+  Pythia8_i(const string &name, ISvcLocator *pSvcLocator);
+  
+  ~Pythia8_i();
+  
+  virtual StatusCode genInitialize();
+  virtual StatusCode callGenerator();
+  virtual StatusCode fillEvt(GenEvent *evt);
+  virtual StatusCode genFinalize();
+
+  double pythiaVersion()const;
+  
+  static std::string    pythia_stream;
+    
+protected:
+  
+  // make these protected so that Pythia8B can access them
+  Pythia8::Pythia m_pythia;
+  HepMC::Pythia8ToHepMC m_pythiaToHepMC;
+
+private:
+  
+  static std::string xmlpath();
+  
+//  StoreGateSvc* m_sGateService;
+//  string m_mcEventKey;
+  
+  int m_internal_event_number;
+  
+  double m_version;
+  
+  std::vector<std::string> m_commands;
+  
+  enum PDGID {PROTON=2212, ANTIPROTON=-2212, ELECTRON=11, POSITRON=-11, INVALID=0};
+  
+  double m_collisionEnergy;
+  bool m_useRndmGenSvc;
+  customRndm *m_atlasRndmEngine; 
+
+  
+  std::string m_beam1;
+  std::string m_beam2;
+
+  std::string m_lheFile;
+  
+  unsigned int m_maxFailures;
+  unsigned int m_failureCount;
+  
+  std::map<std::string, PDGID> m_particleIDs;
+
+  std::vector<long int> m_seeds;
+
+  std::string m_userProcess;
+
+  // ptr to possible user process
+  Pythia8::Sigma2Process *m_procPtr;
+  
+  std::string m_userHook;
+  
+  Pythia8::UserHooks *m_userHookPtr;
+  
+  std::string m_userResonances;
+  
+  vector<Pythia8::ResonanceWidths*> m_userResonancePtrs;
+  
+  bool m_useLHAPDF;
+
+  std::string m_particleDataFile;
+  std::string m_outputParticleDataFile;
+  
+};
+
+#endif
diff --git a/Generators/Pythia8_i/Pythia8_i/UserHooksFactory.h b/Generators/Pythia8_i/Pythia8_i/UserHooksFactory.h
new file mode 100644
index 00000000000..a9cebaaf0ef
--- /dev/null
+++ b/Generators/Pythia8_i/Pythia8_i/UserHooksFactory.h
@@ -0,0 +1,69 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef GENERATOR_PYTHIA8_USER_HOOKS_FACTORY_H
+#define GENERATOR_PYTHIA8_USER_HOOKS_FACTORY_H
+
+#include "Pythia8/UserHooks.h"
+
+#include <string>
+
+namespace Pythia8_UserHooks{
+ 
+  using Pythia8::UserHooks;
+  using std::string;
+  
+  
+  class UserHooksFactory{
+    
+  public:
+    
+    static UserHooks* create(const string &hookName);
+    
+  private:
+    
+    UserHooksFactory(){};
+    
+    class ICreator{
+    public:
+      virtual UserHooks *create() const = 0;
+      virtual ~ICreator(){};
+    };
+    
+  public:
+    
+    template <class T>
+    class Creator: public ICreator{
+      
+    public:
+      
+      Creator(const string &name){
+        m_name = name;
+        UserHooksFactory::s_creators()[name] = this;
+      }
+      
+      ~Creator(){
+        if(s_creators()[m_name] == this){
+          s_creators().erase(m_name);
+        }
+      }
+      
+      UserHooks *create()const{
+        return new T;
+      }
+      
+    private:
+      
+      string m_name;
+    };
+    
+  private:
+    
+    static map<string, const ICreator*> &s_creators();
+    
+  };
+}
+
+
+#endif
diff --git a/Generators/Pythia8_i/Pythia8_i/UserProcessFactory.h b/Generators/Pythia8_i/Pythia8_i/UserProcessFactory.h
new file mode 100644
index 00000000000..fe3bb8d825c
--- /dev/null
+++ b/Generators/Pythia8_i/Pythia8_i/UserProcessFactory.h
@@ -0,0 +1,70 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef GENERATOR_PYTHIA8_USER_PROCESS_FACTORY_H
+#define GENERATOR_PYTHIA8_USER_PROCESS_FACTORY_H
+
+#include "Pythia8/SigmaProcess.h"
+
+#include <boost/smart_ptr.hpp>
+
+#include <map>
+#include <string>
+
+namespace Pythia8_UserProcess{
+  
+  using Pythia8::Sigma2Process;
+    
+  using std::string;
+  using std::map;
+  
+  class UserProcessFactory{
+    
+  public:
+    
+    static Sigma2Process* create(const string &procName);
+    
+  private:
+    
+    UserProcessFactory(){};
+    
+    class ICreator{
+    public:
+      virtual Sigma2Process *create() const = 0;
+      virtual ~ICreator(){};
+    };
+    
+  public:
+    
+    template <class T>
+    class Creator: public ICreator{
+      
+    public:
+      Creator(const string &name){
+        m_name = name;
+        UserProcessFactory::s_creators()[name] = this;
+      }
+      
+      ~Creator(){
+        if(s_creators()[m_name] == this){
+          s_creators().erase(m_name);
+        }
+      }
+      
+      Sigma2Process *create()const{
+        return new T;
+      }
+      
+    private:
+      
+      string m_name;
+      
+    };
+    
+  private:
+    static map<string, const ICreator*> &s_creators();
+    
+  };
+}
+#endif
diff --git a/Generators/Pythia8_i/Pythia8_i/UserResonanceFactory.h b/Generators/Pythia8_i/Pythia8_i/UserResonanceFactory.h
new file mode 100644
index 00000000000..32736c4bb00
--- /dev/null
+++ b/Generators/Pythia8_i/Pythia8_i/UserResonanceFactory.h
@@ -0,0 +1,72 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef GENERATOR_PYTHIA8_USER_RESONANCE_FACTORY_H
+#define GENERATOR_PYTHIA8_USER_RESONANCE_FACTORY_H
+
+#include "Pythia8/ResonanceWidths.h"
+
+#include <string>
+
+namespace Pythia8_UserResonance{
+ 
+  using Pythia8::ResonanceWidths;
+  using std::string;
+  using std::map;
+  
+  class UserResonanceFactory{
+    
+  public:
+    
+    /**
+     *  Call this with the name of the ResonanceWidth and PDG ID to which it will be applied
+     *  e.g. create("MyResonance", 23) will return a MyResonance instance that will be applied to the Z
+     *
+     */
+    static ResonanceWidths* create(const string &name, int pdgid);
+    
+  private:
+    
+    UserResonanceFactory(){};
+    
+    class ICreator{
+    public:
+      virtual ResonanceWidths *create(int idResIn)const = 0;
+      virtual ~ICreator(){};
+    };
+    
+  public:
+    
+    template <class T>
+    class Creator: public ICreator{
+      
+    public:
+      Creator(const string &name){
+        m_name = name;
+        UserResonanceFactory::s_creators()[name] = this;
+      }
+      
+      ~Creator(){
+        if(s_creators()[m_name] == this){
+          s_creators().erase(m_name);
+        }
+      }
+      
+      ResonanceWidths *create(int idResIn)const{
+        return new T(idResIn);
+      }
+      
+    private:
+      
+      string m_name;
+    };
+    
+  private:
+    
+    static map<string, const ICreator*> &s_creators();
+    
+  };
+}
+
+#endif
diff --git a/Generators/Pythia8_i/cmt/requirements b/Generators/Pythia8_i/cmt/requirements
new file mode 100644
index 00000000000..b9b83a15d70
--- /dev/null
+++ b/Generators/Pythia8_i/cmt/requirements
@@ -0,0 +1,35 @@
+package Pythia8_i
+
+author James Monk <jmonk@hep.ucl.ac.uk>
+
+use    AtlasPolicy         AtlasPolicy-*
+use    AtlasBoost          AtlasBoost-*          External
+use    Lhapdf              Lhapdf-*              External
+use    Pythia8             Pythia8-*             External
+use    GeneratorModules    GeneratorModules-*    Generators
+use    AthenaKernel        AthenaKernel-*        Control
+use    AtlasCLHEP          AtlasCLHEP-*          External
+
+private
+
+use    GaudiInterface      GaudiInterface-*      External
+###use    AtlasHepMC          AtlasHepMC-*          External
+use    GeneratorObjects    GeneratorObjects-*    Generators
+
+macro_append Pythia8_i_pp_cppflags ' -DPY8VERSION=\"$(Pythia8_version)\" '
+macro_append fflags "" Linux ""
+
+# The dependencies of the various generator packages need to be sorted out
+# so that they work in full asNeeded/noUndefined mode. Until that time, this
+# package explicitly sets the allowUndefined tag
+#apply_tag allowUndefined
+apply_tag notAsNeeded
+end_private
+
+macro_append pythia8_ifiles 'Pythia8_i.cxx UserProcessFactory.cxx UserHooksFactory.cxx UserResonanceFactory.cxx'
+macro_append UserProcessFiles 'UserProcesses/Sigma2qqbar2emu.cxx UserProcesses/Sigma2qqbar2lStarlBar.cxx UserProcesses/Sigma2qqbar2lStarlStarBar.cxx'
+macro_append UserHookFiles 'UserHooks/WZVetoedShower.cxx UserHooks/QCDVetoedShower.cxx UserHooks/PoWHEGVetoedShower.cxx UserHooks/GravFlat.cxx UserHooks/SuppressMPI.cxx UserHooks/EnhanceMPI.cxx UserHooks/ISRVetoedShower.cxx UserHooks/PTRelVetoedShower.cxx UserHooks/WprimeFlat.cxx UserHooks/WprimeWZFlat.cxx UserHooks/main31.cxx'
+macro_append UserResonanceFiles 'UserResonances/ResonanceExcitedCI.cxx'
+
+apply_pattern named_dual_use_library library="Pythia8_i" files="$(pythia8_ifiles) $(UserProcessFiles) $(UserHookFiles) $(UserResonanceFiles)"
+apply_pattern declare_joboptions files="*.py"
diff --git a/Generators/Pythia8_i/share/Powheg.ZMu.MC11.events b/Generators/Pythia8_i/share/Powheg.ZMu.MC11.events
new file mode 100644
index 00000000000..43e4e334f74
--- /dev/null
+++ b/Generators/Pythia8_i/share/Powheg.ZMu.MC11.events
@@ -0,0 +1,208 @@
+<LesHouchesEvents version="1.0">
+<!--
+file generated with POWHEG-BOX version 1.0
+Input file powheg.input contained:
+!Single vector boson production parameters
+idvecbos 23   ! PDG code for vector boson to be produced ( W+:24 W-:-24 )
+vdecaymode 2  ! PDG code for charged decay product of the vector boson (11:e-; -11:e+; ...)
+ 
+numevts 10    ! number of events to be generated
+ih1   1           ! hadron 1 (1 for protons, -1 for antiprotons)
+ih2   1           ! hadron 2 (1 for protons, -1 for antiprotons)
+ndns1 131         ! pdf set for hadron 1 (mlm numbering)
+ndns2 131         ! pdf set for hadron 2 (mlm numbering)
+ebeam1 3500d0      ! energy of beam 1
+ebeam2 3500d0      ! energy of beam 2
+ 
+! To be set only if using LHA pdfs
+lhans1 10800      ! pdf set for hadron 1 (LHA numbering)
+lhans2 10800      ! pdf set for hadron 2 (LHA numbering)	
+! To be set only if using different pdf sets for the two incoming hadrons
+! QCDLambda5  0.25 ! for not equal pdf sets
+ 
+! Parameters to allow or not the use of stored data
+use-old-grid    1 ! if 1 use old grid if file pwggrids.dat is present (<> 1 regenerate)
+use-old-ubound  1 ! if 1 use norm of upper bounding function stored in pwgubound.dat, if present; <>
+ 
+ncall1 120000   ! number of calls for initializing the integration grid
+itmx1    5     ! number of iterations for initializing the integration grid
+ncall2 250000   ! number of calls for computing the integral and finding upper bound
+itmx2    5     ! number of iterations for computing the integral and finding upper bound
+foldcsi   1    ! number of folds on csi integration
+foldy     1    ! number of folds on  y  integration
+foldphi   1    ! number of folds on phi integration
+nubound 20000  ! number of bbarra calls to setup norm of upper bounding function
+icsimax  1     ! <= 100, number of csi subdivision when computing the upper bounds
+iymax    1     ! <= 100, number of y subdivision when computing the upper bounds
+xupbound 2d0   ! increase upper bound for radiation generation
+ 
+! OPTIONAL PARAMETERS
+ 
+!SM parameters
+ 
+Zmass 91.1876 ! Z mass in GeV
+Zwidth 2.4952 ! Z width in GeV
+sthw2 0.23113 ! sin**2 theta w
+!alphaem 0.0072973 ! em coupling 1/137
+alphaem 0.00781653 ! em coupling 1/127
+Wmass 80.399 ! W mass in GeV
+Wwidth 2.085 ! W width in GeV
+ 
+CKM_Vud 0.97428
+CKM_Vus 0.2253
+CKM_Vub 0.00347
+CKM_Vcd 0.2252
+CKM_Vcs 0.97345
+CKM_Vcb 0.0410
+CKM_Vtd 0.00862
+CKM_Vts 0.0403
+CKM_Vtb 0.999152
+ 
+masswindow_low 15. ! M Z > Zmass - masswindow low * Zwidth
+masswindow_high 5000. ! M Z < Zmass + masswindow high * Zwidth
+ 
+runningscale 1 ! choice for ren and fac scales in Bbar integration
+               !0: fixed scale M Z
+               !1: running scale inv mass Z
+               !2: running scale transverse mass Z
+renscfact  1d0   ! (default 1d0) ren scale factor: muren  = muref * renscfact
+facscfact  1d0   ! (default 1d0) fac scale factor: mufact = muref * facscfact
+# withdamp    1      ! (default 0, do not use) use Born-zero damping factor
+pdfreweight 1      ! (default 0) write extra pdf infos on LHEF
+ 
+! RANDOM NUMBER SEEDS
+ 
+iseed 1    ! initialize random number sequence
+rand1     -1      ! initialize random number sequence
+rand2     -1      ! initialize random number sequence
+ 
+ 
+#ptsupp     0d0   ! (default 0d0)  mass param for Born suppression factor (generation cut) If < 0 su
+#bornonly   0      ! (default 0) if 1 do Born only
+#smartsig   1      ! (default 1) remember equal amplitudes (0 do not remember)
+#withsubtr  0      ! (default 1) subtract real counterterms (0 do not subtract)
+#ptsqmin    0.8    ! (default 0.8 GeV) minimum pt for generation of radiation
+#charmthr   1.5    ! (default 1.5 GeV) charm treshold for gluon splitting
+#bottomthr  5.0    ! (default 5.0 GeV) bottom treshold for gluon splitting
+#testplots  1      ! (default 0, do not) do NLO and PWHG distributions
+#hfact    100d0    ! (default no dumping factor) dump factor for high-pt radiation: > 0 dumpfac=h**2
+#testsuda  1       ! (default 0, do not test) test Sudakov form factor
+#radregion 1       ! (default all regions) only generate radiation in the selected singular region
+#charmthrpdf  1.5  ! (default 1.5 GeV) pdf charm treshold
+#bottomthrpdf 5.0  ! (default 5.0 GeV) pdf bottom treshold
+ 
+#iupperisr 1 ! (default 1) choice of ISR upper bounding functional form
+#iupperfsr 2 ! (default 2) choice of FSR upper bounding functional form
+ 
+#manyseeds 1 ! (default 0) allow for the generation of different statistically independent samples (
+End of powheg.input content
+ Random number generator initialized with:            1      33627373             0
+-->
+<init>
+     2212     2212  3.50000E+03  3.50000E+03     -1     -1     -1     -1      3      1
+  9.67831E+02  2.67947E-01  1.00000E+00  10013
+</init>
+<event>
+      6  10013  1.00000E+00  2.82379E+00 -1.00000E+00  3.04932E-01
+       1    -1     0     0   501     0  0.000000000E+00  0.000000000E+00  3.607458198E+02  3.607458198E+02  0.000000000E+00  0.00000E+00  9.000E+00
+      -1    -1     0     0     0   511  0.000000000E+00  0.000000000E+00 -6.454449689E+00  6.454449689E+00  0.000000000E+00  0.00000E+00  9.000E+00
+      23     2     1     2     0     0 -2.323316383E-01  2.814217670E+00  3.520085741E+02  3.635691599E+02  9.090942750E+01  0.00000E+00  9.000E+00
+      13     1     3     3     0     0 -3.948222587E+00  3.481745721E+00 -4.569218708E+00  6.971365587E+00  1.056583668E-01  0.00000E+00  9.000E+00
+     -13     1     3     3     0     0  3.715890949E+00 -6.675280510E-01  3.565777928E+02  3.565977943E+02  1.056583669E-01  0.00000E+00  9.000E+00
+      21     1     1     2   501   511  2.323316383E-01 -2.814217670E+00  2.282796027E+00  3.631109580E+00  6.615340996E-08  0.00000E+00  9.000E+00
+#pdf   1 -1 0.10217611E+00 0.16507161E-02 0.90909428E+02 0.35811953E+00 0.11922570E+01 1.
+</event>
+<event>
+      6  10013  1.00000E+00  1.56447E+00 -1.00000E+00  4.21196E-01
+       3    -1     0     0   501     0  0.000000000E+00  0.000000000E+00  9.713038824E+00  9.713038824E+00  0.000000000E+00  0.00000E+00  9.000E+00
+      -3    -1     0     0     0   511  0.000000000E+00  0.000000000E+00 -2.407279087E+02  2.407279087E+02  0.000000000E+00  0.00000E+00  9.000E+00
+      23     2     1     2     0     0  8.179690066E-01  1.333599350E+00 -2.032460040E+02  2.226280464E+02  9.083975624E+01  0.00000E+00  9.000E+00
+      13     1     3     3     0     0  2.384785824E+01 -2.242676161E+01 -2.461580450E+01  4.095886929E+01  1.056583668E-01  0.00000E+00  9.000E+00
+     -13     1     3     3     0     0 -2.302988924E+01  2.376036096E+01 -1.786301995E+02  1.816691771E+02  1.056583668E-01  0.00000E+00  9.000E+00
+      21     1     1     2   501   511 -8.179690066E-01 -1.333599350E+00 -2.776886588E+01  2.781290119E+01  4.128186458E-07  0.00000E+00  9.000E+00
+#pdf   3 -3 0.27684526E-02 0.60830129E-01 0.90839756E+02 0.91714285E+00 0.12179079E+00 
+</event>
+<event>
+      6  10013  1.00000E+00  1.12054E+02 -1.00000E+00  1.21623E-01
+       2    -1     0     0   501     0  0.000000000E+00  0.000000000E+00  8.018857281E+02  8.018857281E+02  0.000000000E+00  0.00000E+00  9.000E+00
+      21    -1     0     0   511   501  0.000000000E+00  0.000000000E+00 -2.822868203E+01  2.822868203E+01  0.000000000E+00  0.00000E+00  9.000E+00
+      23     2     1     2     0     0  9.287337735E+01 -6.269504394E+01  2.224186047E+02  2.676022307E+02  9.790191727E+01  0.00000E+00  9.000E+00
+      13     1     3     3     0     0 -8.657041539E+00 -4.183373359E+01  4.445776523E+01  6.165638399E+01  1.056583668E-01  0.00000E+00  9.000E+00
+     -13     1     3     3     0     0  1.015304189E+02 -2.086131035E+01  1.779608394E+02  2.059458467E+02  1.056583668E-01  0.00000E+00  9.000E+00
+       2     1     1     2   511     0 -9.287337735E+01  6.269504394E+01  5.512384414E+02  5.625121795E+02  6.125084199E-06  0.00000E+00  9.000E+00
+#pdf   2 -2 0.46058511E-01 0.42469429E-02 0.97901917E+02 0.63591894E+00 0.79446277E+00
+</event>
+<event>
+      6  10013  1.00000E+00  1.00369E+01 -1.00000E+00  1.95514E-01
+       2    -1     0     0   501     0  0.000000000E+00  0.000000000E+00  2.010003947E+02  2.010003947E+02  0.000000000E+00  0.00000E+00  9.000E+00
+      -2    -1     0     0     0   511  0.000000000E+00  0.000000000E+00 -1.529721111E+01  1.529721111E+01  0.000000000E+00  0.00000E+00  9.000E+00
+      23     2     1     2     0     0  3.141951762E+00 -9.532469809E+00  1.839949162E+02  2.061163476E+02  9.235301690E+01  0.00000E+00  9.000E+00
+      13     1     3     3     0     0  1.232415980E+01 -3.569065842E+01  2.632963771E+01  4.603226041E+01  1.056583668E-01  0.00000E+00  9.000E+00
+     -13     1     3     3     0     0 -9.182208041E+00  2.615818861E+01  1.576652784E+02  1.600840872E+02  1.056583668E-01  0.00000E+00  9.000E+00
+      21     1     1     2   501   511 -3.141951762E+00  9.532469809E+00  1.708267440E+00  1.018125823E+01  2.122164147E-07  0.00000E+00  9.000E+00
+#pdf   2 -2 0.55403944E-01 0.31417051E-02 0.92353017E+02 0.62989306E+00 0.90292466E+00
+</event>
+<event>
+      6  10013  1.00000E+00  1.04202E+01 -1.00000E+00  1.93656E-01
+       3    -1     0     0   501     0  0.000000000E+00  0.000000000E+00  1.332282132E+02  1.332282132E+02  0.000000000E+00  0.00000E+00  9.000E+00
+      -3    -1     0     0     0   511  0.000000000E+00  0.000000000E+00 -2.326270033E+01  2.326270033E+01  0.000000000E+00  0.00000E+00  9.000E+00
+      23     2     1     2     0     0 -1.021549498E+01  2.055254461E+00  1.126918126E+02  1.457199749E+02  9.179480396E+01  0.00000E+00  9.000E+00
+      13     1     3     3     0     0 -2.308841974E+00  1.220137428E+01 -1.380625449E+01  1.856954798E+01  1.056583668E-01  0.00000E+00  9.000E+00
+     -13     1     3     3     0     0 -7.906653006E+00 -1.014611982E+01  1.264980671E+02  1.271504269E+02  1.056583668E-01  0.00000E+00  9.000E+00
+      21     1     1     2   501   511  1.021549498E+01 -2.055254461E+00 -2.726299782E+00  1.077093864E+01  1.933845970E-07  0.00000E+00  9.000E+00
+#pdf   3 -3 0.36680396E-01 0.46881997E-02 0.91794804E+02 0.20111262E+00 0.72101262E+00
+</event>
+<event>
+      6  10013  1.00000E+00  1.59194E+01 -1.00000E+00  1.74937E-01
+       2    -1     0     0   501     0  0.000000000E+00  0.000000000E+00  6.771182630E+01  6.771182630E+01  0.000000000E+00  0.00000E+00  9.000E+00
+      21    -1     0     0   511   501  0.000000000E+00  0.000000000E+00 -4.157412921E+01  4.157412921E+01  0.000000000E+00  0.00000E+00  9.000E+00
+      23     2     1     2     0     0  2.738398956E+00  1.568213068E+01  3.627724513E+01  9.041167445E+01  8.126994716E+01  0.00000E+00  9.000E+00
+      13     1     3     3     0     0 -2.886571268E+00 -1.222412057E+01 -2.212432259E+01  2.544127023E+01  1.056583668E-01  0.00000E+00  9.000E+00
+     -13     1     3     3     0     0  5.624970224E+00  2.790625125E+01  5.840156771E+01  6.497040422E+01  1.056583668E-01  0.00000E+00  9.000E+00
+       2     1     1     2   511     0 -2.738398956E+00 -1.568213068E+01 -1.013954804E+01  1.887428107E+01  2.469673610E-07  0.00000E+00  9.000E+00
+#pdf   2 -2 0.17760880E-01 0.75892595E-02 0.81269947E+02 0.68683024E+00 0.59404329E+00
+</event>
+<event>
+      6  10013  1.00000E+00  2.66750E+01 -1.00000E+00  1.56633E-01
+      -3    -1     0     0     0   511  0.000000000E+00  0.000000000E+00  4.528832990E+01  4.528832990E+01  0.000000000E+00  0.00000E+00  9.000E+00
+       3    -1     0     0   501     0  0.000000000E+00  0.000000000E+00 -1.351504985E+02  1.351504985E+02  0.000000000E+00  0.00000E+00  9.000E+00
+      23     2     1     2     0     0  2.433492024E+01 -1.092564348E+01 -1.111498417E+02  1.463107893E+02  9.132908482E+01  0.00000E+00  9.000E+00
+      13     1     3     3     0     0 -2.101434561E-01 -2.802960983E+01 -1.129147169E+02  1.163419427E+02  1.056583668E-01  0.00000E+00  9.000E+00
+     -13     1     3     3     0     0  2.454506369E+01  1.710396635E+01  1.764875200E+00  2.996884657E+01  1.056583668E-01  0.00000E+00  9.000E+00
+      21     1     1     2   501   511 -2.433492024E+01  1.092564348E+01  2.128767307E+01  3.412803910E+01  6.425450858E-07  0.00000E+00  9.000E+00
+#pdf  -3  3 0.48215418E-02 0.35304998E-01 0.91329085E+02 0.71114296E+00 0.20783819E+00
+</event>
+<event>
+      6  10013  1.00000E+00  1.47555E+01 -1.00000E+00  1.78011E-01
+      -1    -1     0     0     0   501  0.000000000E+00  0.000000000E+00  7.623749254E+01  7.623749254E+01  0.000000000E+00  0.00000E+00  9.000E+00
+      21    -1     0     0   501   511  0.000000000E+00  0.000000000E+00 -4.136031431E+01  4.136031431E+01  0.000000000E+00  0.00000E+00  9.000E+00
+      23     2     1     2     0     0 -1.208561607E+01  8.465327255E+00  2.106795380E+01  9.738843872E+01  9.393042871E+01  0.00000E+00  9.000E+00
+      13     1     3     3     0     0 -3.299092274E+01 -5.810500577E+00 -2.702423006E+01  4.304048181E+01  1.056583668E-01  0.00000E+00  9.000E+00
+     -13     1     3     3     0     0  2.090530668E+01  1.427582783E+01  4.809218386E+01  5.434795691E+01  1.056583668E-01  0.00000E+00  9.000E+00
+      -1     1     1     2     0   511  1.208561607E+01 -8.465327255E+00  1.380922443E+01  2.020936814E+01  3.537064561E-07  0.00000E+00  9.000E+00
+#pdf  -1  1 0.16717332E-01 0.10770840E-01 0.93930429E+02 0.41769435E+00 0.66171399E+00
+</event>
+<event>
+      6  10013  1.00000E+00  2.16022E+00 -1.00000E+00  3.47947E-01
+       1    -1     0     0   511     0  0.000000000E+00  0.000000000E+00  7.250822326E+02  7.250822326E+02  0.000000000E+00  0.00000E+00  9.000E+00
+      -1    -1     0     0     0   501  0.000000000E+00  0.000000000E+00 -4.300923230E+00  4.300923230E+00  0.000000000E+00  0.00000E+00  9.000E+00
+      23     2     1     2     0     0 -2.140464289E+00 -2.915204767E-01  4.678954473E+02  4.764880672E+02  9.005588318E+01  0.00000E+00  9.000E+00
+      13     1     3     3     0     0  2.359202157E+01  3.683460625E+01  1.920555977E+02  1.969739461E+02  1.056583668E-01  0.00000E+00  9.000E+00
+     -13     1     3     3     0     0 -2.573248586E+01 -3.712612672E+01  2.758398496E+02  2.795141211E+02  1.056583668E-01  0.00000E+00  9.000E+00
+      21     1     1     2   511   501  2.140464289E+00  2.915204767E-01  2.528858621E+02  2.528950886E+02  1.066240300E-06  0.00000E+00  9.000E+00
+#pdf   1 -1 0.13487313E+00 0.12271641E-02 0.90055883E+02 0.31305398E+00 0.13403693E+01
+</event>
+<event>
+      6  10013  1.00000E+00  3.43348E+00 -1.00000E+00  2.80022E-01
+       2    -1     0     0   501     0  0.000000000E+00  0.000000000E+00  8.958829797E+02  8.958829797E+02  0.000000000E+00  0.00000E+00  9.000E+00
+      21    -1     0     0   511   501  0.000000000E+00  0.000000000E+00 -7.087092274E+00  7.087092274E+00  0.000000000E+00  0.00000E+00  9.000E+00
+      23     2     1     2     0     0  1.159842391E+00  3.231643577E+00  8.929604436E+02  8.975726390E+02  9.081023980E+01  0.00000E+00  9.000E+00
+      13     1     3     3     0     0 -3.567196758E+01  1.692535072E+01  6.710009277E+02  6.721615973E+02  1.056583670E-01  0.00000E+00  9.000E+00
+     -13     1     3     3     0     0  3.683180997E+01 -1.369370714E+01  2.219595159E+02  2.254110417E+02  1.056583669E-01  0.00000E+00  9.000E+00
+       2     1     1     2   511     0 -1.159842391E+00 -3.231643577E+00 -4.164556187E+00  5.397432984E+00  4.029991083E-07  0.00000E+00  9.000E+00
+#pdf   2 -2 0.25560780E+00 0.65841460E-03 0.90810240E+02 0.41014918E+00 0.17034656E+01
+</event>
+</LesHouchesEvents>
+ #Random number generator exit values:            1      34256472             0
+
+
diff --git a/Generators/Pythia8_i/share/enhanceMPI_example.py b/Generators/Pythia8_i/share/enhanceMPI_example.py
new file mode 100644
index 00000000000..01a6e458edb
--- /dev/null
+++ b/Generators/Pythia8_i/share/enhanceMPI_example.py
@@ -0,0 +1,12 @@
+# example JO for using the EnhanceMPI plugin
+# For testing only - not validated for production yet!!
+
+evgenConfig.description = "Example QCD jets with MPI enhanced with UserHook"
+evgenConfig.keywords = ["QCD", "MPI"]
+include("MC12JobOptions/Pythia8_AU2_CTEQ6L1_Common.py")
+
+topAlg.Pythia8.Commands += ["HardQCD:all=on",
+                            "PhaseSpace:pTHatMin=60"]
+topAlg.Pythia8.UserHook = "EnhanceMPI"
+
+
diff --git a/Generators/Pythia8_i/share/jobOptions.pythia8.py b/Generators/Pythia8_i/share/jobOptions.pythia8.py
new file mode 100644
index 00000000000..66c34e32e04
--- /dev/null
+++ b/Generators/Pythia8_i/share/jobOptions.pythia8.py
@@ -0,0 +1,12 @@
+include("GeneratorUtils/StdEvgenSetup.py")
+
+svcMgr.MessageSvc.OutputLevel = INFO
+svcMgr.AtRndmGenSvc.Seeds = ["PYTHIA8 4789899 989240512",
+                             "PYTHIA8_INIT 820021 2347532"]
+
+from Pythia8_i.Pythia8_iConf import Pythia8_i
+topAlg += Pythia8_i()
+topAlg.Pythia8_i.CollisionEnergy = 7000
+topAlg.Pythia8_i.Commands += ['HardQCD:all = on']
+
+include("GeneratorUtils/postJO.DumpMC.py")
diff --git a/Generators/Pythia8_i/share/lhef_example.py b/Generators/Pythia8_i/share/lhef_example.py
new file mode 100644
index 00000000000..20a33472ca9
--- /dev/null
+++ b/Generators/Pythia8_i/share/lhef_example.py
@@ -0,0 +1,32 @@
+#import AthenaCommon.AtlasUnixGeneratorJob
+from AthenaCommon.AppMgr import ServiceMgr as svcMgr
+
+#--------------------------------------------------------------
+# Event related parameters
+#--------------------------------------------------------------
+# Number of events to be processed (default is 10)
+theApp.EvtMax = 10
+#--------------------------------------------------------------
+# Algorithms Private Options
+#--------------------------------------------------------------
+from AthenaServices.AthenaServicesConf import AtRndmGenSvc
+ServiceMgr += AtRndmGenSvc()
+ServiceMgr.AtRndmGenSvc.Seeds = ["PYTHIA8 4789899 989240512",
+                                 "PYTHIA8_INIT 820021 2347532"]
+
+svcMgr.MessageSvc.OutputLevel = INFO
+
+from AthenaCommon.AlgSequence import AlgSequence
+topSequence = AlgSequence()
+from Pythia8_i.Pythia8_iConf import Pythia8_i
+
+topSequence+=Pythia8_i()
+topSequence.Pythia8_i.CollisionEnergy = 7000
+
+topSequence.Pythia8_i.LHEFile = "Powheg.ZMu.MC11.events"
+
+
+from TruthExamples.TruthExamplesConf import DumpMC
+topSequence += DumpMC()
+
+
diff --git a/Generators/Pythia8_i/share/qcdVetoedShowerExample.py b/Generators/Pythia8_i/share/qcdVetoedShowerExample.py
new file mode 100644
index 00000000000..8f0c1e39163
--- /dev/null
+++ b/Generators/Pythia8_i/share/qcdVetoedShowerExample.py
@@ -0,0 +1,36 @@
+#import AthenaCommon.AtlasUnixGeneratorJob
+from AthenaCommon.AppMgr import ServiceMgr as svcMgr
+
+#--------------------------------------------------------------
+# Event related parameters
+#--------------------------------------------------------------
+# Number of events to be processed (default is 10)
+theApp.EvtMax = 10
+#--------------------------------------------------------------
+# Algorithms Private Options
+#--------------------------------------------------------------
+from AthenaServices.AthenaServicesConf import AtRndmGenSvc
+ServiceMgr += AtRndmGenSvc()
+ServiceMgr.AtRndmGenSvc.Seeds = ["PYTHIA8 4789899 989240512",
+                                 "PYTHIA8_INIT 820021 2347532"]
+
+svcMgr.MessageSvc.OutputLevel = INFO
+
+from AthenaCommon.AlgSequence import AlgSequence
+topSequence = AlgSequence()
+from Pythia8_i.Pythia8_iConf import Pythia8_i
+
+topSequence+=Pythia8_i()
+topSequence.Pythia8_i.CollisionEnergy = 7000
+
+#topSequence.Pythia8_i.Commands += ['WeakSingleBoson:ffbar2gmZ = on']
+topSequence.Pythia8_i.LHEFile = "Powheg.ZMu.MC11.events"
+
+topSequence.Pythia8_i.Commands += ['SpaceShower:pTmaxMatch = 2']
+topSequence.Pythia8_i.Commands += ['TimeShower:pTmaxMatch  = 2']
+topSequence.Pythia8_i.UserHook = "QCDVetoedShower"
+
+from TruthExamples.TruthExamplesConf import DumpMC
+topSequence += DumpMC()
+
+
diff --git a/Generators/Pythia8_i/share/suppressMPI_example.py b/Generators/Pythia8_i/share/suppressMPI_example.py
new file mode 100644
index 00000000000..5c64b3ab561
--- /dev/null
+++ b/Generators/Pythia8_i/share/suppressMPI_example.py
@@ -0,0 +1,12 @@
+# example JO for using the SuppressMPI plugin
+# For testing only - not validated for production yet!!
+
+evgenConfig.description = "Example QCD jets with MPI suppressed with UserHook"
+evgenConfig.keywords = ["QCD", "MPI"]
+include("MC12JobOptions/Pythia8_AU2_CTEQ6L1_Common.py")
+
+topAlg.Pythia8.Commands += ["HardQCD:all=on",
+                            "PhaseSpace:pTHatMin=60"]
+topAlg.Pythia8.UserHook = "SuppressMPI"
+
+
diff --git a/Generators/Pythia8_i/share/userProcess_example.py b/Generators/Pythia8_i/share/userProcess_example.py
new file mode 100644
index 00000000000..b5cca22532f
--- /dev/null
+++ b/Generators/Pythia8_i/share/userProcess_example.py
@@ -0,0 +1,36 @@
+#import AthenaCommon.AtlasUnixGeneratorJob
+from AthenaCommon.AppMgr import ServiceMgr as svcMgr
+
+#--------------------------------------------------------------
+# Event related parameters
+#--------------------------------------------------------------
+# Number of events to be processed (default is 10)
+theApp.EvtMax = 3
+#--------------------------------------------------------------
+# Algorithms Private Options
+#--------------------------------------------------------------
+from AthenaServices.AthenaServicesConf import AtRndmGenSvc
+ServiceMgr += AtRndmGenSvc()
+ServiceMgr.AtRndmGenSvc.Seeds = ["PYTHIA8 4789899 989240512",
+                                 "PYTHIA8_INIT 820021 2347532"]
+
+svcMgr.MessageSvc.OutputLevel = INFO
+
+from AthenaCommon.AlgSequence import AlgSequence
+topSequence = AlgSequence()
+from Pythia8_i.Pythia8_iConf import Pythia8_i
+
+
+topSequence+=Pythia8_i()
+topSequence.Pythia8_i.useRndmGenSvc = True
+topSequence.Pythia8_i.UserProcess = "qqbar2emu"
+
+#topSequence.Pythia8_i.Commands += ['Random:setSeed = on']
+#topSequence.Pythia8_i.Commands += ['Random:seed = 123456789']
+
+#topSequence.Pythia8_i.CollisionEnergy = 10000
+
+from TruthExamples.TruthExamplesConf import DumpMC
+topSequence += DumpMC()
+
+
diff --git a/Generators/Pythia8_i/share/vetoedISR_example.py b/Generators/Pythia8_i/share/vetoedISR_example.py
new file mode 100644
index 00000000000..f4eb2a344e1
--- /dev/null
+++ b/Generators/Pythia8_i/share/vetoedISR_example.py
@@ -0,0 +1,35 @@
+#import AthenaCommon.AtlasUnixGeneratorJob
+from AthenaCommon.AppMgr import ServiceMgr as svcMgr
+
+#--------------------------------------------------------------
+# Event related parameters
+#--------------------------------------------------------------
+# Number of events to be processed (default is 10)
+theApp.EvtMax = 10
+#--------------------------------------------------------------
+# Algorithms Private Options
+#--------------------------------------------------------------
+from AthenaServices.AthenaServicesConf import AtRndmGenSvc
+ServiceMgr += AtRndmGenSvc()
+ServiceMgr.AtRndmGenSvc.Seeds = ["PYTHIA8 4789899 989240512",
+                                 "PYTHIA8_INIT 820021 2347532"]
+
+svcMgr.MessageSvc.OutputLevel = INFO
+
+from AthenaCommon.AlgSequence import AlgSequence
+topSequence = AlgSequence()
+from Pythia8_i.Pythia8_iConf import Pythia8_i
+
+topSequence+=Pythia8_i()
+topSequence.Pythia8_i.CollisionEnergy = 7000
+
+topSequence.Pythia8_i.LHEFile = "Powheg.ZMu.MC11.events"
+
+topSequence.Pythia8_i.Commands += ['SpaceShower:pTmaxMatch = 2',
+                                   'TimeShower:pTmaxMatch  = 1']
+topSequence.Pythia8_i.UserHook = "ISRVetoedShower"
+
+from TruthExamples.TruthExamplesConf import DumpMC
+topSequence += DumpMC()
+
+
diff --git a/Generators/Pythia8_i/src/Pythia8_i.cxx b/Generators/Pythia8_i/src/Pythia8_i.cxx
new file mode 100644
index 00000000000..6a2bb8cf3c8
--- /dev/null
+++ b/Generators/Pythia8_i/src/Pythia8_i.cxx
@@ -0,0 +1,410 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "Pythia8_i/Pythia8_i.h"
+#include "Pythia8_i/UserProcessFactory.h"
+#include "Pythia8_i/UserHooksFactory.h"
+#include "Pythia8_i/UserResonanceFactory.h"
+
+#include "GeneratorObjects/McEventCollection.h"
+#include <boost/algorithm/string.hpp>
+#include <boost/lexical_cast.hpp>
+
+// calls to fortran routines
+#include "CLHEP/Random/RandFlat.h"
+#include "AthenaKernel/IAtRndmGenSvc.h"
+
+// Name of AtRndmGenSvc stream
+std::string     Pythia8_i::pythia_stream   = "PYTHIA8_INIT";
+
+/**
+ * author: James Monk (jmonk@cern.ch)
+ */
+////////////////////////////////////////////////////////////////////////////////
+Pythia8_i::Pythia8_i(const string &name, ISvcLocator *pSvcLocator)
+: GenModule(name, pSvcLocator),
+m_pythia(xmlpath()),
+m_internal_event_number(0),
+m_version(-1.),
+m_atlasRndmEngine(0),
+m_failureCount(0),
+m_procPtr(0),
+m_userHookPtr(0)
+{
+  declareProperty("Commands", m_commands);
+  declareProperty("CollisionEnergy", m_collisionEnergy = 14000.0);
+  declareProperty("useRndmGenSvc", m_useRndmGenSvc = true);
+  declareProperty("Beam1", m_beam1 = "PROTON");
+  declareProperty("Beam2", m_beam2 = "PROTON");
+  declareProperty("LHEFile", m_lheFile = "");
+  declareProperty("MaxFailures", m_maxFailures = 10);//the max number of consecutive failures
+  declareProperty("UserProcess", m_userProcess="");
+  declareProperty("UserHook", m_userHook="");
+  declareProperty("UserResonances", m_userResonances="");
+  declareProperty("UseLHAPDF", m_useLHAPDF=true);
+  declareProperty("ParticleData", m_particleDataFile="");
+  declareProperty("OutputParticleData",m_outputParticleDataFile="ParticleData.local.xml");
+  
+  m_particleIDs["PROTON"]     = PROTON;
+  m_particleIDs["ANTIPROTON"] = ANTIPROTON;
+  m_particleIDs["ELECTRON"]   = ELECTRON;
+  m_particleIDs["POSITRON"]   = POSITRON;
+
+}
+
+////////////////////////////////////////////////////////////////////////////////
+Pythia8_i::~Pythia8_i() {
+
+  delete m_atlasRndmEngine;
+  
+  if(m_procPtr != 0)     delete m_procPtr;
+  if(m_userHookPtr != 0) delete m_userHookPtr;
+  
+}
+
+////////////////////////////////////////////////////////////////////////////////
+StatusCode Pythia8_i::genInitialize() {
+
+  ATH_MSG_DEBUG("Pythia8_i from genInitialize()");
+  
+  m_version = m_pythia.settings.parm("Pythia:versionNumber");
+  
+  std::string pythiaVersion = boost::lexical_cast<std::string>(m_version + 0.00000000001);
+  pythiaVersion.erase(5);
+  std::string libVersion = "8." + std::string(PY8VERSION);
+  
+  if(pythiaVersion != libVersion){
+    ATH_MSG_ERROR("Version of Pythia in xmldoc (" + pythiaVersion + ") does not matched linked library version (" + libVersion + ")");
+    return StatusCode::FAILURE;
+  }
+  
+  Pythia8_i::pythia_stream =       "PYTHIA8_INIT";
+
+  // Default LEP tune is LEP 1 (previously Tune:ee = 3).
+  // Not setting it should be identical, so we don't anymore!
+  
+  // LEP1 tune for hadronisation.  Default from version 8.125 anyway
+  //  m_pythia.readString("Tune:ee = 3");
+  
+  // We do explicitly set tune 4C, since it is the starting point for many other tunes
+  // Tune 4C for pp collisions (default from 8.150 anyway)
+  m_pythia.readString("Tune:pp = 5");
+
+  // but also use LHAPDF and CTEQ6L1 unless otherwise instructed in JO
+  if(m_useLHAPDF){
+    m_pythia.readString("PDF:useLHAPDF = on");
+    m_pythia.readString("PDF:LHAPDFset = cteq6ll.LHpdf");
+  }else{
+    m_pythia.readString("PDF:useLHAPDF = off");
+  }
+    
+  // Now apply the settings from the JO
+  for(vector<string>::const_iterator cmd = m_commands.begin();
+      cmd != m_commands.end(); ++cmd){
+    bool read = m_pythia.readString(*cmd);
+    
+    if(!read){
+      ATH_MSG_ERROR("Pythia could not understand the command '"<< *cmd<<"'");
+      return StatusCode::FAILURE;
+    }
+  }
+
+  PDGID beam1 = m_particleIDs[m_beam1];
+  PDGID beam2 = m_particleIDs[m_beam2];
+
+  ATH_MSG_INFO("Beam1 = "<<beam1);
+  ATH_MSG_INFO("Beam2 = "<<beam2);
+
+  if(beam1 == 0 || beam2 == 0){
+    ATH_MSG_ERROR("Invalid beam particle!");
+    return StatusCode::FAILURE;
+  }
+
+  if(m_useRndmGenSvc){
+
+    ATH_MSG_INFO(" !!!!!!!!!!!!  WARNING ON PYTHIA RANDOM NUMBERS !!!!!!!!!! ");
+    ATH_MSG_INFO("           THE ATHENA SERVICE AtRndmGenSvc IS USED.");
+    ATH_MSG_INFO(" !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ");
+
+    if(m_atlasRndmEngine) delete m_atlasRndmEngine;
+    m_atlasRndmEngine = new customRndm();
+
+    m_atlasRndmEngine->init(atRndmGenSvc(),Pythia8_i::pythia_stream);
+    m_pythia.setRndmEnginePtr(m_atlasRndmEngine);
+
+    // Save the PYTHIA_INIT stream seeds....
+    CLHEP::HepRandomEngine* engine = atRndmGenSvc().GetEngine(Pythia8_i::pythia_stream);
+
+    const long*   sip     =       engine->getSeeds();
+    long  int     si1     =       sip[0];
+    long  int     si2     =       sip[1];
+
+    atRndmGenSvc().CreateStream(si1, si2, Pythia8_i::pythia_stream);
+    Pythia8_i::pythia_stream =       "PYTHIA8";
+    m_atlasRndmEngine->m_stream=Pythia8_i::pythia_stream;
+
+  }else{
+    ATH_MSG_INFO(" !!!!!!!!!!!!  WARNING ON PYTHIA RANDOM NUMBERS !!!!!!!!!! ");
+    ATH_MSG_INFO("    THE STANDARD PYTHIA8 RANDOM NUMBER SERVICE IS USED.");
+    ATH_MSG_INFO("    THE ATHENA SERVICE AtRndmGenSvc IS ***NOT*** USED.");
+    ATH_MSG_INFO(" !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ");
+  }
+
+  m_procPtr = 0;
+
+  if(m_userProcess != ""){
+    m_procPtr = Pythia8_UserProcess::UserProcessFactory::create(m_userProcess);
+  }
+
+  bool canInit = true;
+  
+  m_userHookPtr = 0;
+
+  if(m_userHook != ""){
+    m_userHookPtr = Pythia8_UserHooks::UserHooksFactory::create(m_userHook);
+    if(!m_pythia.setUserHooksPtr(m_userHookPtr)){
+      ATH_MSG_ERROR("Unable to set requested user hook: " + m_userHook + " !!");
+      ATH_MSG_ERROR("Pythia 8 initialisation will FAIL!");
+      canInit = false;
+    }
+  }
+
+  if(m_userResonances != ""){
+   
+    vector<string> resonanceArgs;
+    
+    boost::split(resonanceArgs, m_userResonances, boost::is_any_of(":"));
+    if(resonanceArgs.size() != 2){
+      ATH_MSG_ERROR("Cannot Understand UserResonance job option!");
+      ATH_MSG_ERROR("You should specify it as a 'name:id1,id2,id3...'");
+      ATH_MSG_ERROR("Where name is the name of your UserResonance, and id1,id2,id3 are a comma separated list of PDG IDs to which it is applied");
+      canInit = false;
+    }
+    vector<string> resonanceIds;
+    boost::split(resonanceIds, resonanceArgs.back(), boost::is_any_of(","));
+    if(resonanceIds.size()==0){
+      ATH_MSG_ERROR("You did not specifiy any PDG ids to which your user resonance width should be applied!");
+      ATH_MSG_ERROR("You should specify a list as 'name:id1,id2,id3...'");
+      ATH_MSG_ERROR("Where name is the name of your UserResonance, and id1,id2,id3 are a comma separated list of PDG IDs to which it is applied");
+      canInit=false;
+    }
+    
+    for(vector<string>::const_iterator sId = resonanceIds.begin();
+        sId != resonanceIds.end(); ++sId){
+      int idResIn = boost::lexical_cast<int>(*sId);
+      m_userResonancePtrs.push_back(Pythia8_UserResonance::UserResonanceFactory::create(resonanceArgs.front(), idResIn));
+    }
+    
+    for(vector<Pythia8::ResonanceWidths*>::const_iterator resonance = m_userResonancePtrs.begin();
+        resonance != m_userResonancePtrs.end(); ++resonance){
+      m_pythia.setResonancePtr(*resonance);
+    }
+    
+  }
+  
+  if(m_particleDataFile != "") {
+    if(!m_pythia.particleData.reInit(m_particleDataFile, true)){
+      ATH_MSG_ERROR("Unable to read requested particle data table: " + m_particleDataFile + " !!");
+      ATH_MSG_ERROR("Pythia 8 initialisation will FAIL!");
+      canInit = false;
+    }
+  }
+  
+  if(m_lheFile != ""){
+    if(!m_pythia.init(m_lheFile)){
+      ATH_MSG_ERROR("Unable to read requested LHE file: " + m_lheFile + " !!");
+      ATH_MSG_ERROR("Pythia 8 initialisation will FAIL!");
+      canInit = false;
+    }
+  }else{
+    if(m_procPtr != 0){
+      if(!m_pythia.setSigmaPtr(m_procPtr)){
+        ATH_MSG_ERROR("Unable to set requested user process: " + m_userProcess + " !!");
+        ATH_MSG_ERROR("Pythia 8 initialisation will FAIL!"); 
+        canInit = false;
+      }
+    }
+    if(!m_pythia.init(beam1, beam2, m_collisionEnergy)){
+      ATH_MSG_ERROR("Unable to initialise Pythia beams !!");
+      ATH_MSG_ERROR("Pythia 8 initialisation will FAIL!");
+      canInit = false;
+    }
+  }
+
+  StatusCode returnCode = SUCCESS;
+  
+  if(!canInit){
+    returnCode = StatusCode::FAILURE;
+    ATH_MSG_ERROR(" *** Unable to initialise Pythia !! ***");
+  }
+  
+  m_pythia.settings.listChanged();
+  m_pythia.particleData.listChanged();
+  m_pythia.particleData.listXML(m_outputParticleDataFile);
+  
+  //counter for event failures;
+  m_failureCount = 0;
+
+  m_internal_event_number = 0;
+  
+  m_pythiaToHepMC.set_store_pdf(true);
+  
+  return returnCode;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+StatusCode Pythia8_i::callGenerator(){
+
+  ATH_MSG_DEBUG(">>> Pythia8_i from callGenerator");
+
+  if(m_useRndmGenSvc){
+    // Save the random number seeds in the event
+    CLHEP::HepRandomEngine*  engine  = atRndmGenSvc().GetEngine(Pythia8_i::pythia_stream);
+    const long* s =  engine->getSeeds();
+    m_seeds.clear();
+    m_seeds.push_back(s[0]);
+    m_seeds.push_back(s[1]);
+  }
+
+  bool status = m_pythia.next();
+
+  StatusCode returnCode = StatusCode::SUCCESS;
+
+  if(!status){
+    ++m_failureCount;
+    if(m_failureCount >= m_maxFailures){
+      ATH_MSG_ERROR("Exceeded the max number of consecutive event failures.");
+      returnCode =  StatusCode::FAILURE;
+    }else{
+      ATH_MSG_INFO("Event generation failed - re-trying.");
+      returnCode = this->callGenerator();
+    }
+  }
+
+  m_failureCount = 0;
+  
+  // some CKKWL merged events have zero weight (or unfilled event). 
+  // start again with such events
+  if(fabs(m_pythia.info.mergingWeight()*m_pythia.info.weight()) < 1.e-18 ||
+     m_pythia.event.size() < 2) 
+    returnCode = this->callGenerator(); 
+  
+  ++m_internal_event_number;
+
+  return returnCode;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+StatusCode Pythia8_i::fillEvt(GenEvent *evt){
+
+  ATH_MSG_DEBUG(">>> Pythia8_i from fillEvt");
+
+  evt->set_event_number(m_internal_event_number);
+
+  if(m_pythia.event.size() < 2){
+    ATH_MSG_ERROR("Something wrong with this event - it contains fewer than 2 particles!");
+    ATH_MSG_ERROR("internal event number is "<<m_internal_event_number);
+    return StatusCode::FAILURE;
+  }
+  
+  m_pythiaToHepMC.fill_next_event(m_pythia, evt, m_internal_event_number);
+
+  // in debug mode you can check whether the pdf information is stored
+  if(evt->pdf_info()){
+    ATH_MSG_DEBUG("PDFinfo id1:" << evt->pdf_info()->id1());
+    ATH_MSG_DEBUG("PDFinfo id2:" << evt->pdf_info()->id2());
+    ATH_MSG_DEBUG("PDFinfo x1:" << evt->pdf_info()->x1());
+    ATH_MSG_DEBUG("PDFinfo x2:" << evt->pdf_info()->x2());
+    ATH_MSG_DEBUG("PDFinfo scalePDF:" << evt->pdf_info()->scalePDF());
+    ATH_MSG_DEBUG("PDFinfo pdf1:" << evt->pdf_info()->pdf1());
+    ATH_MSG_DEBUG("PDFinfo pdf2:" << evt->pdf_info()->pdf2());
+  }
+  else
+    ATH_MSG_DEBUG("No PDF information available in HepMC::GenEvent!");
+
+  // set the randomseeds
+  if(m_useRndmGenSvc)evt->set_random_states(m_seeds);
+  
+  double phaseSpaceWeight = m_pythia.info.weight();
+  double mergingWeight    = m_pythia.info.mergingWeight();
+  double eventWeight = phaseSpaceWeight*mergingWeight;
+  
+  ATH_MSG_DEBUG("Event weights: phase space weight, merging weight, total weight = "<<phaseSpaceWeight<<", "<<mergingWeight<<", "<<eventWeight);
+  
+  // set the event weight
+  evt->weights().clear();
+  evt->weights().push_back(eventWeight);
+
+  // Units correction
+  #ifdef HEPMC_HAS_UNITS
+  //std::cout << (evt->momentum_unit() == HepMC::Units::GEV ? "GeV" : "MeV") << std::endl;
+  /// @todo We shouldn't be having to rescale these events if they're already in MeV :S Where's the screw-up: HepMC or Py8?
+  /// Hopefully this is permanently fixed in version 8.170 onwards
+  if(pythiaVersion() < 8.170 ){
+    GeVToMeV(evt);
+  }
+  #else
+  ATH_MSG_DEBUG("Not scaling HepMC energies for Py8 > 8.153!");
+  /// @todo We *should* be having to rescale these events! Again, is HepMC or Py8 wrong? Or us?
+  //GeVToMeV(evt);
+  #endif
+
+#ifndef HEPMC_HAS_UNITS
+  ATH_MSG_DEBUG();
+#endif
+  
+  //HepMC::GenEvent *evtCopy = new HepMC::GenEvent(*evt);
+
+  return SUCCESS;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+StatusCode Pythia8_i::genFinalize(){
+
+  ATH_MSG_INFO(">>> Pythia8_i from genFinalize");
+
+  m_pythia.stat();
+  
+  Pythia8::Info info = m_pythia.info;
+  double xs = info.sigmaGen();// in mb
+  xs *= 1000. * 1000.;//convert to nb
+
+  std::cout << "MetaData: cross-section (nb)= " << xs <<std::endl;
+  std::cout << "MetaData: generator= Pythia 8." << PY8VERSION <<std::endl;
+
+  return SUCCESS;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+double Pythia8_i::pythiaVersion()const{
+  return m_version;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+string Pythia8_i::xmlpath(){
+    
+  char *cmtpath = getenv("CMTPATH");
+  char *cmtconfig = getenv("CMTCONFIG");
+  
+  string foundpath = "";
+  
+  if(cmtpath != 0 && cmtconfig != 0){
+    
+    vector<string> cmtpaths;
+    boost::split(cmtpaths, cmtpath, boost::is_any_of(string(":")));
+    
+    string installPath = "/InstallArea/" + string(cmtconfig) + "/share/Pythia8/xmldoc";
+    
+    for(vector<string>::const_iterator path = cmtpaths.begin();
+        path != cmtpaths.end() && foundpath == ""; ++path){
+      string testPath = *path + installPath;
+      std::ifstream testFile(testPath.c_str());
+      if(testFile.good()) foundpath = testPath;
+      testFile.close();
+    }
+    
+  }
+  
+  return foundpath;
+}
diff --git a/Generators/Pythia8_i/src/UserHooks/EnhanceMPI.cxx b/Generators/Pythia8_i/src/UserHooks/EnhanceMPI.cxx
new file mode 100644
index 00000000000..6c771551649
--- /dev/null
+++ b/Generators/Pythia8_i/src/UserHooks/EnhanceMPI.cxx
@@ -0,0 +1,104 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "UserHooksUtils.h"
+#include "Pythia8_i/UserHooksFactory.h"
+#include "boost/lexical_cast.hpp"
+#include <stdexcept>
+#include <iostream>
+
+namespace Pythia8{
+  class EnhanceMPI;
+}
+
+Pythia8_UserHooks::UserHooksFactory::Creator<Pythia8::EnhanceMPI> EnhanceMPICreator("EnhanceMPI");
+
+namespace Pythia8{
+
+  class EnhanceMPI : public UserHooks{
+    
+  public:
+    
+    EnhanceMPI(): m_pTCut(10.), m_nMPIVeto(3){
+      
+      std::cout<<"**********************************************************"<<std::endl;
+      std::cout<<"*                                                        *"<<std::endl;
+      std::cout<<"*        Enhancing MPI emissions with UserHook!          *"<<std::endl;
+      std::cout<<"*                                                        *"<<std::endl;
+      std::cout<<"**********************************************************"<<std::endl;
+
+      m_passedEvent = 0;      
+    }
+    
+    ~EnhanceMPI(){}
+    
+    bool doVetoMPIStep(int nMPI, const Event &event){
+      
+      // MPI 1 is the hard process.  We do not veto that!
+      if(nMPI < 2){
+        m_passedEvent = false;
+        return false;
+      }
+      
+      if(m_passedEvent) return false;
+      
+      // start at the end of the event record and work back
+      // This is prior to showering, so there should be at most 2 new MPI emissions
+      // event[0] is documentation, so stop before that.
+      size_t nEmissions=0;
+      for(int ii=event.size()-1; ii > 0 && nEmissions != 2; --ii){
+        if(event[ii].status() != 33) continue;
+        if(event[ii].pT() > m_pTCut){
+          m_passedEvent = true;
+          return false;
+        }
+        
+        ++nEmissions;
+      }
+      
+      if(nMPI == m_nMPIVeto && !m_passedEvent){
+        //        std::cout<<"Vetoing event on too-little MPI"<<std::endl;
+        return true;
+      }
+      
+      return false;
+    }
+    
+    bool doVetoPartonLevel(const Event&){
+      if(m_passedEvent) return false;
+      
+      return true;
+    }
+    
+    /// Switch on calling of doVetoMPIStep
+    bool canVetoMPIStep(){return true;}
+    /// Call doVetoMIStep three times
+    /// First is the hard process
+    /// second is first MPI emission 
+    ///           *or* 
+    /// the second part of a double diffractive event
+    ///           *or*
+    /// the second hard process if there is on.
+    /// Therefore check up to 3
+    int numberVetoMPIStep(){return m_nMPIVeto;}
+    /// Switch on veto of ISR
+    bool canVetoISREmission(){return false;}
+    /// Switch off veto of FSR
+    bool canVetoFSREmission(){return false;}
+    /// Check the event after the generation of the parton level but before hadronisation
+    bool canVetoPartonLevel(){return true;}
+    
+  private:
+    
+    double m_pTCut;
+    
+    bool m_passedEvent;
+    
+    int m_nMPIVeto;
+         
+  };
+  
+  
+
+}
diff --git a/Generators/Pythia8_i/src/UserHooks/GravFlat.cxx b/Generators/Pythia8_i/src/UserHooks/GravFlat.cxx
new file mode 100644
index 00000000000..f83217d1a39
--- /dev/null
+++ b/Generators/Pythia8_i/src/UserHooks/GravFlat.cxx
@@ -0,0 +1,117 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "Pythia8_i/UserHooksFactory.h"
+#include "Pythia8/PhaseSpace.h"
+
+namespace Pythia8{
+  class GravFlat;
+}
+
+Pythia8_UserHooks::UserHooksFactory::Creator<Pythia8::GravFlat> gravFlatCreator("GravFlat");
+
+namespace Pythia8 {
+
+  class GravFlat : public UserHooks {
+    
+  public:
+    
+    // Constructor.
+    GravFlat(){}
+    
+    // Destructor.
+    ~GravFlat(){}
+    
+    // Allow process cross section to be modified...
+    virtual bool canModifySigma() {return true;}
+  
+    // ...which gives access to the event at the trial level, before selection.
+    virtual double multiplySigmaBy(const SigmaProcess* sigmaProcessPtr, 
+				   const PhaseSpace* phaseSpacePtr, 
+				   bool /* inEvent */) {
+      // All events should be 2 -> 1, but kill them if not.
+      if (sigmaProcessPtr->nFinal() != 1) return 0.; 
+      
+      // Weight cross section with BW propagator, i.e. to remove it.
+      // (inEvent = false for initialization).
+      // No inEvent criteria, want weight both for cross section 
+      // and MC generation.
+      int idRes   = sigmaProcessPtr->resonanceA();
+      double mRes = particleDataPtr->m0(idRes);
+      double wRes = particleDataPtr->mWidth(idRes);
+      double m2Res   = mRes*mRes;
+      double GamMRat = wRes/mRes;
+      double sHat = phaseSpacePtr->sHat();
+
+      double weightBW = pow2(sHat - m2Res) + pow2(sHat * GamMRat);
+
+      double weightPL = 1;
+      double rH = sqrt(sHat);
+
+      if (rH >= 50 && rH < 2000){
+
+        // Completely Flat M=2 TeV, Above 0.05 TeV, Below 2 TeV
+        // 1e5
+	double p0 = 12.4176;  
+	double p1 = -0.364611;
+	double p2 = 0.00293827;
+	double p3 = 4.3106e-07;
+	double p4 = -2.61662e-09;
+	double p5 = 1.33037e-12;
+	double p6 = -2.07848e-16;
+
+	weightPL = 1/(p0+(p1*rH)+(p2*pow(rH,2))+(p3*pow(rH,3))+(p4*pow(rH,4))+(p5*pow(rH,5))+(p6*pow(rH,6)));
+
+      }
+      else if (rH >= 2000 && rH < 4000){
+
+        // Completely Flat M=2 TeV, Above 2 TeV, Below 4 TeV
+        // 1e5
+	double p0 = 41237.9;  
+	double p1 = -95.9745;
+	double p2 = 0.0979667;
+	double p3 = -5.14644e-05;
+	double p4 = 1.45857e-08;
+	double p5 = -2.13169e-12;
+	double p6 = 1.26473e-16;
+
+	weightPL = 1/(p0+(p1*rH)+(p2*pow(rH,2))+(p3*pow(rH,3))+(p4*pow(rH,4))+(p5*pow(rH,5))+(p6*pow(rH,6)));
+
+      }
+      else if (rH >= 4000 && rH < 5500){
+
+        // Completely Flat M=2 TeV, Above 4 TeV, Below 5.5 TeV
+        // 1e5
+	double p0 = 1.11676e+06;  
+	double p1 = -925.647;
+	double p2 = 0.311595;
+	double p3 = -5.38465e-05;
+	double p4 = 4.92286e-09;
+	double p5 = -2.1452e-13;
+	double p6 = 2.97112e-18;
+
+	weightPL = 1/(p0+(p1*rH)+(p2*pow(rH,2))+(p3*pow(rH,3))+(p4*pow(rH,4))+(p5*pow(rH,5))+(p6*pow(rH,6)));
+
+      }
+      else if (rH >= 5500 && rH <= 6500){
+
+        // Completely Flat M=2 TeV, Above 5.5 TeV, Below 6.5 TeV
+        // 1e5
+	double p0 = 9.70964e+13;  
+	double p1 = -4.17142e-03;
+	double p2 = -3.06415e-03;          
+
+	weightPL = 1/((p0*exp(p1*rH))+(p2*rH));
+
+      }        
+  
+      double weight = weightBW * weightPL;
+    
+      return weight;
+
+    }
+    
+  };  
+
+} // end namespace Pythia8
diff --git a/Generators/Pythia8_i/src/UserHooks/ISRVetoedShower.cxx b/Generators/Pythia8_i/src/UserHooks/ISRVetoedShower.cxx
new file mode 100644
index 00000000000..8aa845e09e2
--- /dev/null
+++ b/Generators/Pythia8_i/src/UserHooks/ISRVetoedShower.cxx
@@ -0,0 +1,173 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "UserHooksUtils.h"
+#include "Pythia8_i/UserHooksFactory.h"
+#include <stdexcept>
+#include <iostream>
+
+namespace Pythia8{
+  class ISRVetoedShower;
+}
+
+Pythia8_UserHooks::UserHooksFactory::Creator<Pythia8::ISRVetoedShower> ISRVetoedShowerCreator("ISRVetoedShower");
+
+namespace Pythia8{
+
+  /**
+   *  This UserHook should be used when showering QCD jets generated with PoWHEG-box.
+   *  The following settings must be activated in Pythia:
+   *
+   *    SpaceShower:pTMaxMatch = 2
+   *    TimeShower:pTMaxMatch  = 1
+   *
+   *  These set the limit for emission from initial state radiation to the kinematic (beam) energy.
+   *  The veto hook then vetos any emission that would be above the appropriate scale.
+   *
+   *  This Hook determines a new (lower) veto scale according to the following prescription: 
+   *  Compute the pT of every PoWHEG leg relative to the beam, and the pT of every outgoing PoWHEG leg relative to all
+   *  the other legs in the CMS frame.  Use the lowest of these values as the new veto scale
+   *
+   *  This hook is ONLY TESTED FOR QCD JET PRODUCTION!!
+   */
+  class ISRVetoedShower : public UserHooks{
+
+  public:
+
+    ISRVetoedShower(): m_powhegScale(0.){
+
+      std::cout<<"*****************************************************"<<std::endl;
+      std::cout<<"*                                                   *"<<std::endl;
+      std::cout<<"*  Using new scale definition for QCD production!   *"<<std::endl;
+      std::cout<<"*  New showering for ISR ONLY - FSR as normal!      *"<<std::endl;
+      std::cout<<"*                                                   *"<<std::endl;
+      std::cout<<"*****************************************************"<<std::endl;
+      
+    }
+
+    ~ISRVetoedShower(){}
+
+    /**
+     *  doVetoMPIStep is called immediately after the MPI generation
+     *  In this case it never actually vetoes the MPI, but since it is called
+     *  before the ISR veto check this is a convenient place to find the PoWHEG
+     *  scale from the LHEF event
+     */
+    bool doVetoMPIStep(int nMPI, const Event &evt){
+
+      // Only do anything on the first call.
+      if(nMPI > 1) return false;
+      
+      m_powhegScale = infoPtr->QRen();;
+      
+      // momentum components to boost to CMS frame
+      double pxCMS = 0.;
+      double pyCMS = 0.;
+      double pzCMS = 0.;
+      double eCMS  = 0.;
+      
+      vector<Particle> powhegLegs;
+      
+      // Find the entries corresponding to outgoing legs from PoWHEG
+      // start the loop at 1, since entry 0 represents the event as a whole
+      for(int ii=1; ii != evt.size(); ++ii){
+
+        // status -21 is the incoming hard partons
+        if(evt[ii].status() == -21){
+          pxCMS += evt[ii].px();
+          pyCMS += evt[ii].py();
+          pzCMS += evt[ii].pz();   
+          eCMS  += evt[ii].e();
+        }
+        
+        // here Event::isFinal refers to whether the particle can still decay/radiate, or whether it is an internal leg
+        if(evt[ii].isFinal()){
+          powhegLegs.push_back(Particle(evt[ii]));
+        }
+      }
+      
+      // compare the pT of each leg to the powheg scale.
+      // Set the scale to the lowest (or leave the scale unchanged if it is already lower)
+      for(vector<Particle>::const_iterator leg=powhegLegs.begin();
+          leg != powhegLegs.end(); ++leg){
+        if(leg->pT() < m_powhegScale )m_powhegScale = leg->pT();
+      }
+      
+      double norm = -1./eCMS;
+      pxCMS *= norm;
+      pyCMS *= norm;
+      pzCMS *= norm;
+      
+      // boost all outgoing legs to the CMS frame
+      for(vector<Particle>::iterator leg=powhegLegs.begin();
+          leg != powhegLegs.end(); ++leg){
+        leg->bst(pxCMS, pyCMS, pzCMS);
+      }
+      
+      for(vector<Particle>::const_iterator leg=powhegLegs.begin();
+          leg != powhegLegs.end(); ++leg){
+        
+        if(leg->pT() < m_powhegScale )m_powhegScale = leg->pT();
+        
+        // calculate the pT relative to each other leg 
+        // if any such pT is lower than the current scale, reset the scale to that value
+        for(vector<Particle>::const_iterator otherLeg = powhegLegs.begin();
+            otherLeg != powhegLegs.end(); ++otherLeg){
+          if(otherLeg == leg) continue;
+          
+          double pTLeg = Pythia8_UserHooks::pTLeg(*leg, *otherLeg);
+
+          if(pTLeg < m_powhegScale) m_powhegScale = pTLeg;
+        }
+      }
+
+//      std::cout<<m_powhegScale<<"  "<<infoPtr->QRen()<<std::endl;
+
+      
+      return false;
+    }
+
+    /**
+     *  This is called after the generation of each new ISR emission
+     *  Can use it to test if the last generated emission is above the
+     *  veto scale
+     *
+     */
+    bool doVetoISREmission(int, const Event &evt, int iSys){
+
+      // only veto emissions from the hard system
+      if(iSys != 0) return false;
+      
+      size_t emission = Pythia8_UserHooks::findLastISREmission(evt);
+
+      // Veto emission above the veto scale
+      if(evt[emission].pT() > m_powhegScale) return true;
+      
+      return false;
+    }
+    /**
+     *  This is similar to the ISR veto
+     *
+     */
+    bool doVetoFSREmission(int, const Event&, int, bool){
+      
+      return false;
+    }
+
+    /// Switch on calling of doVetoMPIStep
+    bool canVetoMPIStep(){return true;}
+    /// Call doVetoMIStep once
+    int numberVetoMPIStep(){return 1;}
+    /// Switch on veto of ISR
+    bool canVetoISREmission(){return true;}
+    /// Switch off veto of FSR
+    bool canVetoFSREmission(){return false;}
+
+  private:
+
+    double m_powhegScale;
+    
+  };
+}
+
diff --git a/Generators/Pythia8_i/src/UserHooks/PTRelVetoedShower.cxx b/Generators/Pythia8_i/src/UserHooks/PTRelVetoedShower.cxx
new file mode 100644
index 00000000000..7fa73342dc4
--- /dev/null
+++ b/Generators/Pythia8_i/src/UserHooks/PTRelVetoedShower.cxx
@@ -0,0 +1,219 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "UserHooksUtils.h"
+#include "Pythia8_i/UserHooksFactory.h"
+#include "boost/lexical_cast.hpp"
+#include <stdexcept>
+#include <iostream>
+
+namespace Pythia8{
+  class PTRelVetoedShower;
+}
+
+Pythia8_UserHooks::UserHooksFactory::Creator<Pythia8::PTRelVetoedShower> pTRelVetoedShowerCreator("PTRelVetoedShower");
+
+namespace Pythia8{
+  
+ /**
+  *  This user hook is derived from the main31 example distributed with Pythia 8 and
+  *  is for use with QCD events generated with PoWHEG.  The following settings must be
+  *  used in Pythia:
+  *
+  *    SpaceShower:pTMaxMatch = 2
+  *    TimeShower:pTMaxMatch  = 2
+  *
+  *  These set the limit for emission from both initial and final state radiation to the kinematic (beam) energy.
+  *  The veto hook then vetos any emission that would be above the appropriate scale.
+  *
+  *  One key difference between this veto and the one implemented in main31 is the determination of the 
+  *  boost to the CMS frame in which the FSR veto is tested.  In main31, that boost is determined 
+  *  on each shower emission, with the result that it evolves due to recoil of the incoming partons
+  *  against ISR.  In this veto, the boost is determined once in each event and does not evolve with recoil
+  */
+ 
+  class PTRelVetoedShower : public UserHooks{
+    
+  public:
+    
+    PTRelVetoedShower(): m_nPoWHEGFinal(2), m_powhegScale(0.){
+      
+      std::cout<<"*************************************************************************"<<std::endl;
+      std::cout<<"*                                                                       *"<<std::endl;
+      std::cout<<"*        Using PTRel vetoed shower for PoWHEG QCD production!           *"<<std::endl;
+      std::cout<<"*                                                                       *"<<std::endl;
+      std::cout<<"*************************************************************************"<<std::endl;
+
+      m_pxCMS = 0;
+      m_pyCMS = 0;
+      m_pzCMS = 0;
+      
+    }
+    
+    ~PTRelVetoedShower(){}
+    
+    /**
+     *  doVetoMPIStep is called immediately after the MPI generation
+     *  In this case it never actually vetoes the MPI, but since it is called
+     *  before the ISR veto check this is a convenient place to find the PoWHEG
+     *  scale from the LHEF event
+     */
+    bool doVetoMPIStep(int nMPI, const Event &evt){
+      
+      // Only do anything on the first call.
+      if(nMPI > 1) return false;
+      
+      m_powhegScale = infoPtr->QRen();
+
+      size_t nPwgOutgoing = 0;
+      
+      for(int ii = evt.size()-1; ii > 0; --ii){
+        if(! (evt[ii].isFinal())) break;
+        ++nPwgOutgoing;
+      }
+      
+      if(nPwgOutgoing == m_nPoWHEGFinal) return false;
+      
+      if(nPwgOutgoing != m_nPoWHEGFinal + 1){
+        throw std::runtime_error("Wrong number of final state PoWHEG legs: " + boost::lexical_cast<string>(nPwgOutgoing));
+      }
+      
+      // momentum components to boost to CMS frame
+      m_pxCMS = 0.;
+      m_pyCMS = 0.;
+      m_pzCMS = 0.;
+      double eCMS  = 0.;
+      
+      // The outgoing powheg legs
+      vector<Particle> powhegLegs;
+      
+      // Find the entries corresponding to outgoing legs from PoWHEG
+      // start the loop at 1, since entry 0 represents the event as a whole
+      for(int ii=1; ii != evt.size(); ++ii){
+        
+        // status -21 is the incoming hard partons
+        if(evt[ii].status() == -21){
+          m_pxCMS += evt[ii].px();
+          m_pyCMS += evt[ii].py();
+          m_pzCMS += evt[ii].pz();   
+          eCMS  += evt[ii].e();
+        }
+        
+        // here Event::isFinal refers to whether the particle can still decay/radiate, or whether it is an internal leg
+        if(evt[ii].isFinal()){
+          powhegLegs.push_back(Particle(evt[ii]));
+        }
+      }
+      
+      // Start the search for the powheg scale above the collision energy, 
+      // which is guaranteed to be above the veto scale.
+      
+      m_powhegScale = 1.1*infoPtr->s();
+      
+      // compare the pT of each leg to the powheg scale.
+      // Set the scale to the lowest
+      for(vector<Particle>::const_iterator leg=powhegLegs.begin();
+          leg != powhegLegs.end(); ++leg){
+        double pTTmp = leg->pT();
+        if(pTTmp < m_powhegScale )m_powhegScale = pTTmp;
+      }
+      
+      // normalise the boost vector to the CMS frame...
+      double norm = -1./eCMS;
+      m_pxCMS *= norm;
+      m_pyCMS *= norm;
+      m_pzCMS *= norm;
+      
+      // ...and boost all outgoing legs to that frame
+      for(vector<Particle>::iterator leg=powhegLegs.begin();
+          leg != powhegLegs.end(); ++leg){
+        leg->bst(m_pxCMS, m_pyCMS, m_pzCMS);
+      }
+      
+      for(vector<Particle>::const_iterator leg=powhegLegs.begin();
+          leg != powhegLegs.end(); ++leg){
+        // calculate the pT relative to each other leg 
+        // if any such pT is lower than the current scale, reset the scale to that value
+        for(vector<Particle>::const_iterator otherLeg = powhegLegs.begin();
+            otherLeg != powhegLegs.end(); ++otherLeg){
+          if(otherLeg == leg) continue;
+          
+          double pTLeg = Pythia8_UserHooks::pTLeg(*leg, *otherLeg);
+          
+          if(pTLeg < m_powhegScale) m_powhegScale = pTLeg;
+        }
+      }
+      
+      // barf if the scale was not found properly!
+      if(m_powhegScale > infoPtr->s()){
+        throw std::runtime_error("Veto scale could not be determined!");
+      }
+      
+      return false;
+    }
+      
+    /**
+     *  This is called after the generation of each new ISR emission
+     *  Can use it to test if the last generated emission is above the
+     *  veto scale
+     *
+     */
+    bool doVetoISREmission(int, const Event &evt, int iSys){
+      
+      // only veto emissions from the hard system
+      if(iSys != 0) return false;
+      
+      size_t emission = Pythia8_UserHooks::findLastISREmission(evt);
+      
+      if(evt[emission].pT() > m_powhegScale) return true;
+            
+      return false;
+    }
+    
+    /**
+     *  This is similar to the ISR veto
+     *
+     */
+    bool doVetoFSREmission(int, const Event &evt, int iSys, bool){
+      if(iSys != 0) return false;
+      
+      size_t emissionIndex = Pythia8_UserHooks::findLastFSREmission(evt);
+      size_t radiatorIndex = Pythia8_UserHooks::findLastFSRRadiator(evt);
+      
+      Particle emission(evt[emissionIndex]);
+      Particle radiator(evt[radiatorIndex]);
+      
+      emission.bst(m_pxCMS, m_pyCMS, m_pzCMS);
+      radiator.bst(m_pxCMS, m_pyCMS, m_pzCMS);
+      
+      double pTRel = Pythia8_UserHooks::pTLeg(emission, radiator);
+      if(pTRel > m_powhegScale) return true;
+      
+      return false;
+    }
+    
+    
+    /// Switch on calling of doVetoMPIStep
+    bool canVetoMPIStep(){return true;}
+    /// Call doVetoMIStep once
+    int numberVetoMPIStep(){return 1;}
+    /// Switch on veto of ISR
+    bool canVetoISREmission(){return true;}
+    /// Switch off veto of FSR
+    bool canVetoFSREmission(){return true;}
+    
+  private:
+    
+    const size_t m_nPoWHEGFinal;
+    
+    double m_powhegScale;
+    
+    // defines the boost vector to the CMS frame
+    double m_pxCMS;
+    double m_pyCMS;
+    double m_pzCMS;
+    
+  };
+}
+
diff --git a/Generators/Pythia8_i/src/UserHooks/PoWHEGVetoedShower.cxx b/Generators/Pythia8_i/src/UserHooks/PoWHEGVetoedShower.cxx
new file mode 100644
index 00000000000..cce7c4451af
--- /dev/null
+++ b/Generators/Pythia8_i/src/UserHooks/PoWHEGVetoedShower.cxx
@@ -0,0 +1,180 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "UserHooksUtils.h"
+#include "Pythia8_i/UserHooksFactory.h"
+#include <stdexcept>
+#include <iostream>
+
+namespace Pythia8{
+  class PoWHEGVetoedShower;
+}
+
+Pythia8_UserHooks::UserHooksFactory::Creator<Pythia8::PoWHEGVetoedShower> powhegVetoedShowerCreator("PoWHEGVetoedShower");
+
+namespace Pythia8{
+
+  /**
+   *  This UserHook should be used when showering QCD jets generated with PoWHEG-box.
+   *  The following settings must be activated in Pythia:
+   *
+   *    SpaceShower:pTMaxMatch = 2
+   *    TimeShower:pTMaxMatch  = 2
+   *
+   *  These set the limit for emission from both initial and final state radiation to the kinematic (beam) energy.
+   *  The veto hook then vetos any emission that would be above the appropriate scale.
+   *
+   *  This Hook determines a new (lower) veto scale according to the following prescription: 
+   *  Compute the pT of every PoWHEG leg relative to the beam, and the pT of every outgoing PoWHEG leg relative to all
+   *  the other legs in the CMS frame.  Use the lowest of these values as the new veto scale
+   *
+   *  This hook is ONLY SUITABLE FOR QCD JET PRODUCTION!!
+   */
+  class PoWHEGVetoedShower : public UserHooks{
+
+  public:
+
+    PoWHEGVetoedShower(): m_powhegScale(0.){
+
+      std::cout<<"*******************************************************************"<<std::endl;
+      std::cout<<"*                                                                 *"<<std::endl;
+      std::cout<<"*  Using new PoWHEG author scale definition for QCD production!   *"<<std::endl;
+      std::cout<<"*                                                                 *"<<std::endl;
+      std::cout<<"*******************************************************************"<<std::endl;
+      
+    }
+
+    ~PoWHEGVetoedShower(){}
+
+    /**
+     *  doVetoMPIStep is called immediately after the MPI generation
+     *  In this case it never actually vetoes the MPI, but since it is called
+     *  before the ISR veto check this is a convenient place to find the PoWHEG
+     *  scale from the LHEF event
+     */
+    bool doVetoMPIStep(int nMPI, const Event &evt){
+
+      // Only do anything on the first call.
+      if(nMPI > 1) return false;
+      
+      m_powhegScale = infoPtr->QRen();;
+      
+      // momentum components to boost to CMS frame
+      double pxCMS = 0.;
+      double pyCMS = 0.;
+      double pzCMS = 0.;
+      double eCMS  = 0.;
+      
+      vector<Particle> powhegLegs;
+      
+      // Find the entries corresponding to outgoing legs from PoWHEG
+      // start the loop at 1, since entry 0 represents the event as a whole
+      for(int ii=1; ii != evt.size(); ++ii){
+
+        // status -21 is the incoming hard partons
+        if(evt[ii].status() == -21){
+          pxCMS += evt[ii].px();
+          pyCMS += evt[ii].py();
+          pzCMS += evt[ii].pz();   
+          eCMS  += evt[ii].e();
+        }
+        
+        // here Event::isFinal refers to whether the particle can still decay/radiate, or whether it is an internal leg
+        if(evt[ii].isFinal()){
+          powhegLegs.push_back(Particle(evt[ii]));
+        }
+      }
+      
+      // compare the pT of each leg to the powheg scale.
+      // Set the scale to the lowest (or leave the scale unchanged if it is already lower)
+      for(vector<Particle>::const_iterator leg=powhegLegs.begin();
+          leg != powhegLegs.end(); ++leg){
+        if(leg->pT() < m_powhegScale )m_powhegScale = leg->pT();
+      }
+      
+      double norm = -1./eCMS;
+      pxCMS *= norm;
+      pyCMS *= norm;
+      pzCMS *= norm;
+      
+      // boost all outgoing legs to the CMS frame
+      for(vector<Particle>::iterator leg=powhegLegs.begin();
+          leg != powhegLegs.end(); ++leg){
+        leg->bst(pxCMS, pyCMS, pzCMS);
+      }
+      
+      for(vector<Particle>::const_iterator leg=powhegLegs.begin();
+          leg != powhegLegs.end(); ++leg){
+        
+        if(leg->pT() < m_powhegScale )m_powhegScale = leg->pT();
+        
+        // calculate the pT relative to each other leg 
+        // if any such pT is lower than the current scale, reset the scale to that value
+        for(vector<Particle>::const_iterator otherLeg = powhegLegs.begin();
+            otherLeg != powhegLegs.end(); ++otherLeg){
+          if(otherLeg == leg) continue;
+          
+          double pTLeg = Pythia8_UserHooks::pTLeg(*leg, *otherLeg);
+
+          if(pTLeg < m_powhegScale) m_powhegScale = pTLeg;
+        }
+      }
+
+//      std::cout<<m_powhegScale<<"  "<<infoPtr->QRen()<<std::endl;
+
+      
+      return false;
+    }
+
+    /**
+     *  This is called after the generation of each new ISR emission
+     *  Can use it to test if the last generated emission is above the
+     *  veto scale
+     *
+     */
+    bool doVetoISREmission(int, const Event &evt, int iSys){
+
+      // only veto emissions from the hard system
+      if(iSys != 0) return false;
+      
+      size_t emission = Pythia8_UserHooks::findLastISREmission(evt);
+
+      // Veto emission above the veto scale
+      if(evt[emission].pT() > m_powhegScale) return true;
+      
+      return false;
+    }
+    /**
+     *  This is similar to the ISR veto
+     *
+     */
+    bool doVetoFSREmission(int, const Event &evt, int iSys, bool){
+
+      // only veto emissions from the hard system
+      if(iSys != 0) return false;
+      
+      size_t emission = Pythia8_UserHooks::findLastFSREmission(evt);
+
+      // Veto if above the POWHEG scale
+      if (evt[emission].pT() > m_powhegScale) return true;
+      
+      return false;
+    }
+
+    /// Switch on calling of doVetoMPIStep
+    bool canVetoMPIStep(){return true;}
+    /// Call doVetoMIStep once
+    int numberVetoMPIStep(){return 1;}
+    /// Switch on veto of ISR
+    bool canVetoISREmission(){return true;}
+    /// Switch off veto of FSR
+    bool canVetoFSREmission(){return true;}
+
+  private:
+
+    double m_powhegScale;
+    
+  };
+}
+
diff --git a/Generators/Pythia8_i/src/UserHooks/QCDVetoedShower.cxx b/Generators/Pythia8_i/src/UserHooks/QCDVetoedShower.cxx
new file mode 100644
index 00000000000..fa2c01aac40
--- /dev/null
+++ b/Generators/Pythia8_i/src/UserHooks/QCDVetoedShower.cxx
@@ -0,0 +1,138 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "UserHooksUtils.h"
+#include "Pythia8_i/UserHooksFactory.h"
+#include <stdexcept>
+#include <iostream>
+
+namespace Pythia8{
+  class QCDVetoedShower;
+}
+
+Pythia8_UserHooks::UserHooksFactory::Creator<Pythia8::QCDVetoedShower> qcdVetoedShowerCreator("QCDVetoedShower");
+
+namespace Pythia8{
+
+  /**
+   *  This UserHook should be used when showering QCD jets generated with PoWHEG-box.
+   *  The following settings must be activated in Pythia:
+   *
+   *    SpaceShower:pTMaxMatch = 2
+   *    TimeShower:pTMaxMatch  = 2
+   *
+   *  These set the limit for emission from both initial and final state radiation to the kinematic (beam) energy.
+   *  The veto hook then vetos any emission that would be above the appropriate scale.
+   *
+   *  In QCD, emissions could come from any PoWHEG leg, therefore each candidate Pythia emission has its pT determined
+   *  relative to each PoWHEG leg, including the beams.  If any of these pTs is larger than the PoWHEG veto scale then
+   *  that proposed emission is rejected.
+   *
+   *  this differs from colourless resonance production, which requires a different scheme and therefore this hook...
+   *
+   *              ...SHOULD NOT BE USED FOR W/Z OR OTHER COLOURLESS RESONANCE PRODUCTION!!
+   */
+  class QCDVetoedShower : public UserHooks{
+
+  public:
+
+    QCDVetoedShower(): m_powhegScale(0.){
+
+      std::cout<<"*******************************************************************"<<std::endl;
+      std::cout<<"*                                                                 *"<<std::endl;
+      std::cout<<"*        Using vetoed shower for PoWHEG QCD production!           *"<<std::endl;
+      std::cout<<"*                                                                 *"<<std::endl;
+      std::cout<<"*******************************************************************"<<std::endl;
+      
+    }
+
+    ~QCDVetoedShower(){}
+
+    /**
+     *  doVetoMPIStep is called immediately after the MPI generation
+     *  In this case it never actually vetoes the MPI, but since it is called
+     *  before the ISR veto check this is a convenient place to find the PoWHEG
+     *  scale from the LHEF event
+     */
+    bool doVetoMPIStep(int nMPI, const Event &evt){
+
+      // Only do anything on the first call.
+      if(nMPI > 1) return false;
+      
+      m_powhegScale = infoPtr->QRen();
+            
+      m_powhegLegs.clear();
+      // start the loop at 1, since entry 0 represents the event as a whole
+      for(int ii=1; ii != evt.size(); ++ii){
+        // here Event::isFinal refers to whether the particle can still decay/radiate, or whether it is an internal leg
+        if(evt[ii].isFinal()){
+          m_powhegLegs.push_back(ii);
+        }
+      }
+      
+      return false;
+    }
+
+    /**
+     *  This is called after the generation of each new ISR emission
+     *  Can use it to test if the last generated emission is above the
+     *  veto scale
+     *
+     */
+    bool doVetoISREmission(int, const Event &evt, int iSys){
+
+      // only veto emissions from the hard system
+      if(iSys != 0) return false;
+      
+      size_t emission = Pythia8_UserHooks::findLastISREmission(evt);
+
+      return checkEmission(emission, evt);
+
+    }
+    
+    /**
+     *  This is similar to the ISR veto
+     *
+     */
+    bool doVetoFSREmission(int, const Event &evt, int iSys, bool){
+
+      // only veto emissions from the hard system
+      if(iSys != 0) return false;
+      
+      size_t emission = Pythia8_UserHooks::findLastFSREmission(evt);
+
+      return checkEmission(emission, evt);
+    }
+
+    /// Switch on calling of doVetoMPIStep
+    bool canVetoMPIStep(){return true;}
+    /// Call doVetoMIStep once
+    int numberVetoMPIStep(){return 1;}
+    /// Switch on veto of ISR
+    bool canVetoISREmission(){return true;}
+    /// Switch off veto of FSR
+    bool canVetoFSREmission(){return true;}
+
+  private:
+    
+    bool checkEmission(size_t emission, const Event &evt){
+      // Veto if above the POWHEG scale
+      if (evt[emission].pT() > m_powhegScale) return true;
+      
+      // determine pT relative to each outgoing PoWHEG leg and veto if above veto scale
+            
+      for(vector<size_t>::const_iterator legIndex = m_powhegLegs.begin();
+          legIndex != m_powhegLegs.end(); ++legIndex){
+        
+        if(Pythia8_UserHooks::pTLeg(emission, *legIndex, evt) > m_powhegScale)return true;
+      }
+      return false;
+    }
+    
+    double m_powhegScale;
+    // Indices of the PoWHEG legs in the event record
+    vector<size_t> m_powhegLegs;
+  };
+}
+
diff --git a/Generators/Pythia8_i/src/UserHooks/SuppressMPI.cxx b/Generators/Pythia8_i/src/UserHooks/SuppressMPI.cxx
new file mode 100644
index 00000000000..e43691982b3
--- /dev/null
+++ b/Generators/Pythia8_i/src/UserHooks/SuppressMPI.cxx
@@ -0,0 +1,85 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "UserHooksUtils.h"
+#include "Pythia8_i/UserHooksFactory.h"
+#include "boost/lexical_cast.hpp"
+#include <stdexcept>
+#include <iostream>
+
+namespace Pythia8{
+  class SuppressMPI;
+}
+
+Pythia8_UserHooks::UserHooksFactory::Creator<Pythia8::SuppressMPI> SuppressMPICreator("SuppressMPI");
+
+namespace Pythia8{
+
+  class SuppressMPI : public UserHooks{
+    
+  public:
+    
+    SuppressMPI(): m_pTCut(10.){
+      
+      std::cout<<"************************************************************"<<std::endl;
+      std::cout<<"*                                                          *"<<std::endl;
+      std::cout<<"*        Suppressing MPI emissions with UserHook!          *"<<std::endl;
+      std::cout<<"*                                                          *"<<std::endl;
+      std::cout<<"************************************************************"<<std::endl;
+
+      m_nMPIVeto = 0;      
+    }
+    
+    ~SuppressMPI(){}
+    
+    bool doVetoMPIStep(int nMPI, const Event &event){
+      // MPI 1 is the hard process.  We do not veto that!
+      if(nMPI < 2){
+        return false;
+      }
+      
+      // start at the end of the event record and work back
+      // This is prior to showering, so there should be at most 2 new MPI emissions
+      // event[0] is documentation, so stop before that.
+      size_t nEmissions=0;
+      for(int ii=event.size()-1; ii > 0 && nEmissions != 2; --ii){
+        if(event[ii].status() != 33) continue;
+        if(event[ii].pT() > m_pTCut){
+          return true;
+        }
+        
+        ++nEmissions;
+      }
+      
+      return false;
+    }
+    
+    /// Switch on calling of doVetoMPIStep
+    bool canVetoMPIStep(){return true;}
+    /// Call doVetoMIStep three times
+    /// First is the hard process
+    /// second is first MPI emission 
+    ///           *or* 
+    /// the second part of a double diffractive event
+    ///           *or*
+    /// the second hard process if there is on.
+    /// Therefore check up to 3
+    int numberVetoMPIStep(){return m_nMPIVeto;}
+    /// Switch on veto of ISR
+    bool canVetoISREmission(){return false;}
+    /// Switch off veto of FSR
+    bool canVetoFSREmission(){return false;}
+    
+  private:
+    
+    double m_pTCut;
+    
+    int m_nMPIVeto;
+    
+    
+  };
+  
+  
+
+}
diff --git a/Generators/Pythia8_i/src/UserHooks/UserHooksUtils.h b/Generators/Pythia8_i/src/UserHooks/UserHooksUtils.h
new file mode 100644
index 00000000000..0d73d312521
--- /dev/null
+++ b/Generators/Pythia8_i/src/UserHooks/UserHooksUtils.h
@@ -0,0 +1,116 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#ifndef PYTHIA8_USERHOOKS_USERHOOKSUTILS_H
+#define PYTHIA8_USERHOOKS_USERHOOKSUTILS_H
+#include "Pythia8/Event.h"
+#include <stdexcept>
+
+/**
+ *  Some common functions for determining pTs and navigating event records for the PoWHEG + Pythia user hooks
+ */
+
+namespace Pythia8_UserHooks{
+  
+  /**
+   * \return the dot product of \param leg and \param comparison
+   */
+  inline double pTProj(const Pythia8::Particle &leg, const Pythia8::Particle &comparison){
+    return leg.px()*comparison.px() + leg.py()*comparison.py() + leg.pz()*comparison.pz();
+  }
+  
+  /**
+   * \return the dot product of the legs in the \param evt with indices 
+   * \param legIndex and \param comparedIndex
+   */
+  inline double pTProj(size_t legIndex, size_t comparedIndex, const Pythia8::Event &evt){
+    return pTProj(evt[legIndex], evt[comparedIndex]);
+  }
+  
+  /**
+   * \return the pT squared of \param leg relative to \param comparison
+   */
+  inline double pT2Leg(const Pythia8::Particle &leg, const Pythia8::Particle &comparison){
+    double proj = pTProj(leg, comparison);
+    return leg.pAbs2() - (proj*proj) / comparison.pAbs2();
+  }
+  
+  /**
+   * \return the pT squared of the leg with index \param legIndex compared to the leg with index
+   * \param comparedIndex in Event \param evt
+   */
+  inline double pT2Leg(size_t legIndex, size_t comparedIndex, const Pythia8::Event &evt){
+    return pT2Leg(evt[legIndex], evt[comparedIndex]);
+  }
+  
+  /**
+   * \return the pT of \param leg relative to \param comparison
+   */
+  inline double pTLeg(const Pythia8::Particle &leg, const Pythia8::Particle &comparison){
+    return sqrt(pT2Leg(leg, comparison));
+  }
+  
+  /**
+   * \return the pT of the leg with index \param legIndex compared to the leg with index
+   * \param comparedIndex in Event \param evt
+   */
+  inline double pTLeg(size_t legIndex, size_t comparedIndex, const Pythia8::Event &evt){
+    return sqrt(pT2Leg(legIndex, comparedIndex, evt));
+  }
+  
+  /**
+   *  Return the index of the most recent emission in a \param evt with a given \param status
+   */
+  inline size_t findLastEmission(const Pythia8::Event &evt, int status){
+    size_t emission = evt.size() - 1;
+    
+    while(emission != 0){
+      if (evt[emission].isFinal() && evt[emission].status() == status) return emission;
+      
+      --emission;
+    }
+    
+    return 0;
+  }
+  
+  /**
+   * \return the index of the most recent ISR emission in an \param evt
+   */
+  inline size_t findLastISREmission(const Pythia8::Event &evt){
+    size_t emission = findLastEmission(evt, 43);
+    if(emission == 0) throw std::runtime_error("findLastISREmission:: Could not find ISR emission");
+    return emission;
+  }
+  
+  /**
+   * \return the index of the most recent FSR emission in an \param evt
+   */
+  inline size_t findLastFSREmission(const Pythia8::Event &evt){
+    size_t emission = findLastEmission(evt, 51);
+    if(emission == 0) throw std::runtime_error("findLastFSREmission:: Could not find FSR emission");
+    return emission;
+  }
+  
+  /**
+   * \return the index of the most recent particle to radiate an ISR emission in an \param evt
+   */
+  
+  inline size_t findLastISRRadiator(const Pythia8::Event &evt){
+    size_t radiator = findLastEmission(evt, -41);
+    if(radiator == 0) throw std::runtime_error("findLastISRRadiator:: Could not find ISR radiator");
+    return radiator;
+  }
+  
+  /**
+   * \return the index of the most recent particle to radiate a FSR emission in an \param evt
+   */
+  
+  inline size_t findLastFSRRadiator(const Pythia8::Event &evt){
+    size_t emitted = findLastFSREmission(evt);
+    return evt[emitted].mother1();
+  }
+  
+}
+
+#endif
diff --git a/Generators/Pythia8_i/src/UserHooks/VetoedShower.cxx b/Generators/Pythia8_i/src/UserHooks/VetoedShower.cxx
new file mode 100644
index 00000000000..9282b58dbc5
--- /dev/null
+++ b/Generators/Pythia8_i/src/UserHooks/VetoedShower.cxx
@@ -0,0 +1,151 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "Pythia8_i/UserHooksFactory.h"
+#include <stdexcept>
+#include <iostream>
+
+namespace Pythia8{
+  class VetoedShower;
+}
+
+Pythia8_UserHooks::UserHooksFactory::Creator<Pythia8::VetoedShower> vetoedShowerCreator("VetoedShower");
+
+namespace Pythia8{
+
+
+  class VetoedShower : public UserHooks{
+
+  public:
+
+    VetoedShower(): m_pTVeto(0.),  m_doneISR(false){
+      std::cout<<std::endl;
+      std::cout<<"************************************************************************************************"<<std::endl;
+      std::cout<<"Pythia8::VetoedShower: *** WARNING: THIS USER HOOK IS NOT VALIDATED FOR QCD JET PRODUCTION!! ***"<<std::endl;
+      std::cout<<"************************************************************************************************"<<std::endl;
+      std::cout<<std::endl;
+    }
+
+    ~VetoedShower(){}
+
+    /**
+     *  doVetoMPIStep is called immediately after the MPI generation
+     *  In this case it nver actually vetoes the MPI, but since it is called
+     *  before the ISR veto check this is a convenient place to find the veto
+     *  scale from the LHEF event
+     */
+    bool doVetoMPIStep(int, const Event&){
+
+      m_pTVeto = infoPtr->QFac();
+      m_doneISR = false;
+
+//      std::cout<<" ******** veto scale = "<<m_pTVeto<<" *********"<<std::endl;
+
+      return false;
+    }
+
+    /**
+     *  This is called after the generation of each new ISR emission
+     *  Can use it to test if the last generated emission is above the
+     *  veto scale
+     *
+     *  Since the ISR is ordered in pT (with the same definition relative to the
+     *  beam as Powheg), once we find an emission below the veto scale we know that
+     *  all subsequent emissions will also be below the scale.  Therefore m_doneISR
+     *  gets set to true at that point and nothing more needs doing
+     *
+     */
+    bool doVetoISREmission(int, const Event &e, int){
+      // Note ignoring new iSys param for now (addition required to fix compilation against >= 8.157
+
+      if(m_doneISR) return false;
+
+      int i = e.size() - 1;
+
+      while(i != -1){
+
+        if(e[i].isFinal() && e[i].status() == 43) break;
+
+        --i;
+
+        if(i == 0){
+          e.list();
+          throw std::runtime_error("Pythia8::VetoedShower::doVetoISREmission: Could not find ISR emission");
+        }
+      }
+
+      //check the leg is connected to the hard system
+      int iMother = e[i].mother1();
+      if(e[iMother].status() != -41)
+        throw std::runtime_error("Pythia8::VetoedShower::doVetoISREmission: Unexpected status code in ISR");
+
+      iMother = e[iMother].daughter2();
+      if(iMother != partonSystemsPtr->getInA(0) &&
+         iMother != partonSystemsPtr->getInB(0)) return false;
+
+      // Veto emission above the veto scale
+      if(e[i].pT() > m_pTVeto) return true;
+
+      m_doneISR = true;
+      return false;
+    }
+    /**
+     *  This is similar to the ISR veto, with the exception that since the ordering is in
+     *  a slightly different pT definition to Powheg the veto must always be checked, rather
+     *  than stopping once an emission is allowed
+     *
+     */
+    bool doVetoFSREmission(int, const Event &e, int, bool){
+      // Note ignoring new iSys and isResonance params for now (addition required to fix compilation against >= 8.157
+
+      int i = e.size() - 1;
+
+      while(i != -1){
+        if (e[i].isFinal() && e[i].status() == 51) break;
+
+        --i;
+
+        if(i == 0){
+          e.list();
+          throw std::runtime_error("Pythia8::VetoedShower::doVetoFSREmission: Could not find FSR emission");
+        }
+      }
+
+      // Make sure radiation from the hard system
+      int  iMother = e[i].mother1();
+      int  sysSize = partonSystemsPtr->sizeOut(0);
+      bool hardSys = false;
+
+      for (int j = 0; j < sysSize; ++j){
+        int iOut = partonSystemsPtr->getOut(0, j);
+        if (iOut == iMother) {
+          hardSys = true;
+          break;
+        }
+      }
+
+      if (!hardSys) return false;
+
+      // Veto if above the POWHEG scale
+      if (e[i].pT() > m_pTVeto) return true;
+
+      return false;
+    }
+
+    /// Switch on calling of doVetoMPIStep
+    bool canVetoMPIStep(){return true;}
+    /// Call doVetoMIStep once
+    int numberVetoMPIStep(){return 1;}
+    /// Switch on veto of ISR
+    bool canVetoISREmission(){return true;}
+    /// Switch off veto of FSR
+    bool canVetoFSREmission(){return true;}
+
+  private:
+
+    double m_pTVeto;
+    bool m_doneISR;
+  };
+}
+
diff --git a/Generators/Pythia8_i/src/UserHooks/WZVetoedShower.cxx b/Generators/Pythia8_i/src/UserHooks/WZVetoedShower.cxx
new file mode 100644
index 00000000000..efe72b1d32c
--- /dev/null
+++ b/Generators/Pythia8_i/src/UserHooks/WZVetoedShower.cxx
@@ -0,0 +1,128 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "UserHooksUtils.h"
+#include "Pythia8_i/UserHooksFactory.h"
+#include <stdexcept>
+#include <iostream>
+
+namespace Pythia8{
+  class WZVetoedShower;
+}
+
+Pythia8_UserHooks::UserHooksFactory::Creator<Pythia8::WZVetoedShower> wzVetoedShowerCreator("WZVetoedShower");
+
+namespace Pythia8{
+
+  /**
+   *  This UserHook should be used when showering W, Z or other colourless resonances generated with PoWHEG.
+   *  The following setting must be activated in Pythia:
+   *
+   *    SpaceShower:pTMaxMatch = 2
+   *    TimeShower:pTMaxMatch  = 2
+   *
+   *  These set the limit for emission from both initial and final state radiation to the kinematic (beam) energy.
+   *  The veto hook then vetos any emission that would be above the appropriate scale.
+   *
+   *  In the cases of colourless resonance production there should be no FSR emission from PoWHEG, therefore the veto
+   *  determines the pT of every Pythia emission relative to the beam, and vetos if it is above the PoWHEG scale.
+   *
+   *  This is ok because 
+   *
+   *    1) Although you might think the pT should also be determined relative to any PoWHEG ISR emission, there is no way 
+   *       PoWHEG could have generated an emission off its own ISR.
+   *    2) There can be FSR off what was a PoWHEG ISR leg, but again, PoWHEG could never have generated that emission, so you
+   *       only need to compare to the incoming (beam) legs.
+   * 
+   *  This is in contrast to QCD production, which requires a different veto scheme.  As such, this hook...
+   *
+   *               ...SHOULD NOT BE USED FOR QCD JET PRODUCTION!!
+   *
+   */
+
+  class WZVetoedShower : public UserHooks{
+
+  public:
+
+    WZVetoedShower(): m_powhegScale(0.){
+
+      std::cout<<"*******************************************************************"<<std::endl;
+      std::cout<<"*                                                                 *"<<std::endl;
+      std::cout<<"* Using vetoed shower for PoWHEG colourless resonance production! *"<<std::endl;
+      std::cout<<"*                                                                 *"<<std::endl;
+      std::cout<<"*******************************************************************"<<std::endl;
+      
+    }
+
+    ~WZVetoedShower(){}
+
+    /**
+     *  doVetoMPIStep is called immediately after the MPI generation
+     *  In this case it never actually vetoes the MPI, but since it is called
+     *  before the ISR veto check this is a convenient place to find the PoWHEG
+     *  scale from the LHEF event
+     */
+    bool doVetoMPIStep(int nMPI, const Event &){
+
+      // Only do anything on the first call.
+      if(nMPI > 1) return false;
+      
+      m_powhegScale = infoPtr->QRen();
+//      m_powhegScale = infoPtr->QFac();
+
+//      std::cout<<" ******** veto scale = "<<m_powhegScale<<", "<<infoPtr->QRen() <<" *********"<<std::endl;  
+      
+      return false;
+    }
+
+    /**
+     *  This is called after the generation of each new ISR emission
+     *  Can use it to test if the last generated emission is above the
+     *  veto scale
+     *
+     */
+    bool doVetoISREmission(int, const Event &evt, int iSys){
+
+      // only veto emissions from the hard system
+      if(iSys != 0) return false;
+      
+      size_t emission = Pythia8_UserHooks::findLastISREmission(evt);
+
+      // Veto emission above the veto scale
+      if(evt[emission].pT() > m_powhegScale) return true;
+
+      return false;
+    }
+    /**
+     *  This is similar to the ISR veto
+     *
+     */
+    bool doVetoFSREmission(int, const Event &evt, int iSys, bool){
+
+      // only veto emissions from the hard system
+      if(iSys != 0) return false;
+      
+      size_t emission = Pythia8_UserHooks::findLastFSREmission(evt);
+
+      // Veto if above the POWHEG scale
+      if (evt[emission].pT() > m_powhegScale) return true;
+
+      return false;
+    }
+
+    /// Switch on calling of doVetoMPIStep
+    bool canVetoMPIStep(){return true;}
+    /// Call doVetoMIStep once
+    int numberVetoMPIStep(){return 1;}
+    /// Switch on veto of ISR
+    bool canVetoISREmission(){return true;}
+    /// Switch off veto of FSR
+    bool canVetoFSREmission(){return true;}
+
+  private:
+
+    double m_powhegScale;
+  };
+}
+
diff --git a/Generators/Pythia8_i/src/UserHooks/WprimeFlat.cxx b/Generators/Pythia8_i/src/UserHooks/WprimeFlat.cxx
new file mode 100644
index 00000000000..a1b4b934756
--- /dev/null
+++ b/Generators/Pythia8_i/src/UserHooks/WprimeFlat.cxx
@@ -0,0 +1,60 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "Pythia8_i/UserHooksFactory.h"
+#include "Pythia8/PhaseSpace.h"
+
+namespace Pythia8{
+  class WprimeFlat;
+}
+
+Pythia8_UserHooks::UserHooksFactory::Creator<Pythia8::WprimeFlat> WprimeFlatCreator("WprimeFlat");
+
+namespace Pythia8 {
+
+  class WprimeFlat : public UserHooks {
+    
+  public:
+    
+    // Constructor.
+    WprimeFlat(){}
+    
+    // Destructor.
+    ~WprimeFlat(){}
+    
+    // Allow process cross section to be modified...
+    virtual bool canModifySigma() {return true;}
+  
+    // ...which gives access to the event at the trial level, before selection.
+    virtual double multiplySigmaBy(const SigmaProcess* sigmaProcessPtr, 
+				   const PhaseSpace* phaseSpacePtr, 
+				   bool /* inEvent */) {
+      // All events should be 2 -> 1, but kill them if not.
+      if (sigmaProcessPtr->nFinal() != 1) return 0.; 
+      
+      // Weight cross section with BW propagator, i.e. to remove it.
+      // (inEvent = false for initialization).
+      // No inEvent criteria, want weight both for cross section 
+      // and MC generation.
+      int idRes   = sigmaProcessPtr->resonanceA();
+      double mRes = particleDataPtr->m0(idRes);
+      double wRes = particleDataPtr->mWidth(idRes);
+      double m2Res   = mRes*mRes;
+      double GamMRat = wRes/mRes;
+      double sHat = phaseSpacePtr->sHat();
+      double weightBW = pow2(sHat - m2Res) + pow2(sHat * GamMRat);      
+      double m = sqrt(sHat)/8000.0;
+      if(m < 0.0375)
+       weightBW *= 121.88e-12*exp(13.0*m);
+      else
+       weightBW *= 1.0e-12*exp(18.5*m-1.4*log(m));
+
+      return weightBW;
+    }
+    
+  };  
+
+} // end namespace Pythia8
+
+
diff --git a/Generators/Pythia8_i/src/UserHooks/WprimeWZFlat.cxx b/Generators/Pythia8_i/src/UserHooks/WprimeWZFlat.cxx
new file mode 100644
index 00000000000..c27743d2839
--- /dev/null
+++ b/Generators/Pythia8_i/src/UserHooks/WprimeWZFlat.cxx
@@ -0,0 +1,68 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "Pythia8_i/UserHooksFactory.h"
+#include "Pythia8/PhaseSpace.h"
+
+namespace Pythia8{
+  class WprimeWZFlat;
+}
+
+Pythia8_UserHooks::UserHooksFactory::Creator<Pythia8::WprimeWZFlat> WprimeWZFlatCreator("WprimeWZFlat");
+
+namespace Pythia8 {
+  
+  class WprimeWZFlat : public UserHooks {
+    
+  public:
+    
+    // Constructor.
+    WprimeWZFlat(){}
+    
+    // Destructor.
+    ~WprimeWZFlat(){}
+    
+    // Allow process cross section to be modified...
+    virtual bool canModifySigma() {return true;}
+    
+    // ...which gives access to the event at the trial level, before selection.
+    virtual double multiplySigmaBy(const SigmaProcess* sigmaProcessPtr, 
+                                   const PhaseSpace* phaseSpacePtr, 
+                                   bool /* inEvent */) {
+      // All events should be 2 -> 1, but kill them if not.
+      if (sigmaProcessPtr->nFinal() != 1) return 0.; 
+      
+      // Weight cross section with BW propagator, i.e. to remove it.
+      // (inEvent = false for initialization).
+      // No inEvent criteria, want weight both for cross section 
+      // and MC generation.
+      int idRes   = sigmaProcessPtr->resonanceA();
+      double mRes = particleDataPtr->m0(idRes);
+      double wRes = particleDataPtr->mWidth(idRes);
+      double m2Res   = mRes*mRes;
+      double gamMRat = wRes/mRes;
+      double sHat = phaseSpacePtr->sHat();
+      double weightBW = m2Res*m2Res + sHat*sHat*(1 + gamMRat*gamMRat) - 2.*sHat*m2Res;      
+      
+      return weightBW * breitWignerDenom(sqrt(sHat)/8000.0);
+    }
+    
+  private:
+    
+    double breitWignerDenom(double mFrac){
+      
+      if(mFrac < 0.025) return breitWignerDenom(0.025);
+      if(mFrac > 0.6) return breitWignerDenom(0.6);
+      
+      if(mFrac < 0.0425) return 1e-12/(-1.293+1.098e+2*mFrac-2.800e+3*mFrac*mFrac+2.345e+4*mFrac*mFrac*mFrac);
+      if(mFrac < 0.073) return 1.248e-12*(exp(1.158+18.34*mFrac));
+      
+      return 5.733e-10*pow(mFrac,-3.798-0.6555*log(mFrac))/pow(1.427-mFrac,30.017);
+    }
+    
+  };  
+  
+} // end namespace Pythia8
+
+
diff --git a/Generators/Pythia8_i/src/UserHooks/main31.cxx b/Generators/Pythia8_i/src/UserHooks/main31.cxx
new file mode 100644
index 00000000000..3898f605ae0
--- /dev/null
+++ b/Generators/Pythia8_i/src/UserHooks/main31.cxx
@@ -0,0 +1,505 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "UserHooksUtils.h"
+#include "Pythia8_i/UserHooksFactory.h"
+#include "boost/lexical_cast.hpp"
+#include <stdexcept>
+#include <iostream>
+
+namespace Pythia8{
+  class main31;
+}
+
+Pythia8_UserHooks::UserHooksFactory::Creator<Pythia8::main31> main31Creator("Main31");
+
+namespace Pythia8{
+  
+  // Use userhooks to veto PYTHIA emissions above the POWHEG scale.
+  
+  class main31 : public UserHooks {
+    
+  public:  
+    
+    // Constructor and destructor.
+    main31() : nFinal(2),
+    vetoMode(1), vetoCount(3),
+    pThardMode(2), pTemtMode(0),
+    emittedMode(0), pTdefMode(1),
+    MPIvetoMode(0),
+    pThard(0), pTMPI(0),
+    accepted(0),
+    nAcceptSeq(0),
+    nISRveto(0), nFSRveto(0) {};
+    ~main31() {}
+    
+    //--------------------------------------------------------------------------
+    
+    // Routines to calculate the pT (according to pTdefMode) in a splitting:
+    //   ISR: i (radiator after)  -> j (emitted after) k (radiator before)
+    //   FSR: i (radiator before) -> j (emitted after) k (radiator after)
+    // For the Pythia pT definition, a recoiler (after) must be specified.
+    
+    // Compute the Pythia pT separation. Based on pTLund function in History.cc
+    double pTpythia(const Event &e, int RadAfterBranch, int EmtAfterBranch,
+                    int RecAfterBranch, bool FSR) {
+      
+      // Convenient shorthands for later
+      Vec4 radVec = e[RadAfterBranch].p();
+      Vec4 emtVec = e[EmtAfterBranch].p();
+      Vec4 recVec = e[RecAfterBranch].p();
+      int  radID  = e[RadAfterBranch].id();
+      
+      // Calculate virtuality of splitting
+      double sign = (FSR) ? 1. : -1.;
+      Vec4 Q(radVec + sign * emtVec); 
+      double Qsq = sign * Q.m2Calc();
+      
+      // Mass term of radiator
+      double m2Rad = (abs(radID) >= 4 && abs(radID) < 7) ?
+      pow2(particleDataPtr->m0(radID)) : 0.;
+      
+      // z values for FSR and ISR
+      double z, pTnow;
+      if (FSR) {
+        // Construct 2 -> 3 variables
+        Vec4 sum = radVec + recVec + emtVec;
+        double m2Dip = sum.m2Calc();
+        double x1 = 2. * (sum * radVec) / m2Dip;
+        double x3 = 2. * (sum * emtVec) / m2Dip;
+        z     = x1 / (x1 + x3);
+        pTnow = z * (1. - z);
+        
+      } else {
+        // Construct dipoles before/after splitting
+        Vec4 qBR(radVec - emtVec + recVec);
+        Vec4 qAR(radVec + recVec);
+        z     = qBR.m2Calc() / qAR.m2Calc();
+        pTnow = (1. - z);
+      }
+      
+      // Virtuality with correct sign
+      pTnow *= (Qsq - sign * m2Rad);
+      
+      // Can get negative pT for massive splittings
+      if (pTnow < 0.) {
+        cout << "Warning: pTpythia was negative" << endl;
+        return -1.;
+      }
+      
+#ifdef DBGOUTPUT
+      cout << "pTpythia: rad = " << RadAfterBranch << ", emt = "
+      << EmtAfterBranch << ", rec = " << RecAfterBranch
+      << ", pTnow = " << sqrt(pTnow) << endl;
+#endif
+      
+      // Return pT
+      return sqrt(pTnow);
+    }
+    
+    // Compute the POWHEG pT separation between i and j
+    double pTpowheg(const Event &e, int i, int j, bool FSR) {
+      
+      // pT value for FSR and ISR
+      double pTnow = 0.;
+      if (FSR) {
+        // POWHEG d_ij (in CM frame). Note that the incoming beams have not
+        // been updated in the parton systems pointer yet (i.e. prior to any
+        // potential recoil).
+        int iInA = partonSystemsPtr->getInA(0);
+        int iInB = partonSystemsPtr->getInB(0);
+        double betaZ = - ( e[iInA].pz() + e[iInB].pz() ) /
+        ( e[iInA].e()  + e[iInB].e()  );
+                
+        Vec4 iVecBst(e[i].p()), jVecBst(e[j].p());
+        iVecBst.bst(0., 0., betaZ);
+        jVecBst.bst(0., 0., betaZ);
+        pTnow = sqrt( (iVecBst + jVecBst).m2Calc() *
+                     iVecBst.e() * jVecBst.e() /
+                     pow2(iVecBst.e() + jVecBst.e()) );
+        
+      } else {
+        // POWHEG pT_ISR is just kinematic pT
+        pTnow = e[j].pT();
+      }
+      
+      // Check result
+      if (pTnow < 0.) {
+        cout << "Warning: pTpowheg was negative" << endl;
+        return -1.;
+      }
+      
+#ifdef DBGOUTPUT
+      cout << "pTpowheg: i = " << i << ", j = " << j
+      << ", pTnow = " << pTnow << endl;
+#endif
+      
+      return pTnow;
+    }
+    
+    // Calculate pT for a splitting based on pTdefMode.
+    // If j is -1, all final-state partons are tried.
+    // If i, k, r and xSR are -1, then all incoming and outgoing 
+    // partons are tried.
+    // xSR set to 0 means ISR, while xSR set to 1 means FSR
+    double pTcalc(const Event &e, int i, int j, int k, int r, int xSRin) {
+      
+      // Loop over ISR and FSR if necessary
+      double pTemt = -1., pTnow;
+      int xSR1 = (xSRin == -1) ? 0 : xSRin;
+      int xSR2 = (xSRin == -1) ? 2 : xSRin + 1;
+      for (int xSR = xSR1; xSR < xSR2; xSR++) {
+        // FSR flag
+        bool FSR = (xSR == 0) ? false : true;
+        
+        // If all necessary arguments have been given, then directly calculate.
+        // POWHEG ISR and FSR, need i and j.
+        if ((pTdefMode == 0 || pTdefMode == 1) && i > 0 && j > 0) {
+          pTemt = pTpowheg(e, i, j, (pTdefMode == 0) ? false : FSR);
+          
+          // Pythia ISR, need i, j and r.
+        } else if (!FSR && pTdefMode == 2 && i > 0 && j > 0 && r > 0) {
+          pTemt = pTpythia(e, i, j, r, FSR);
+          
+          // Pythia FSR, need k, j and r.
+        } else if (FSR && pTdefMode == 2 && j > 0 && k > 0 && r > 0) {
+          pTemt = pTpythia(e, k, j, r, FSR);
+          
+          // Otherwise need to try all possible combintations.
+        } else {
+          // Start by finding incoming legs to the hard system after
+          // branching (radiator after branching, i for ISR).
+          // Use partonSystemsPtr to find incoming just prior to the
+          // branching and track mothers.
+          int iInA = partonSystemsPtr->getInA(0);
+          int iInB = partonSystemsPtr->getInB(0);
+          while (e[iInA].mother1() != 1) { iInA = e[iInA].mother1(); }
+          while (e[iInB].mother1() != 2) { iInB = e[iInB].mother1(); }
+          
+          // If we do not have j, then try all final-state partons
+          int jNow = (j > 0) ? j : 0;
+          int jMax = (j > 0) ? j + 1 : e.size();
+          for (; jNow < jMax; jNow++) {
+            
+            // Final-state and coloured jNow only
+            if (!e[jNow].isFinal() || e[jNow].colType() == 0) continue;
+            
+            // POWHEG
+            if (pTdefMode == 0 || pTdefMode == 1) {
+              
+              // ISR - only done once as just kinematical pT
+              if (!FSR) {
+                pTnow = pTpowheg(e, iInA, jNow, (pTdefMode == 0) ? false : FSR);
+                if (pTnow > 0.) pTemt = (pTemt < 0) ? pTnow : min(pTemt, pTnow);
+                
+                // FSR - try all outgoing partons from system before branching 
+                // as i. Note that for the hard system, there is no 
+                // "before branching" information.
+              } else {
+                
+                int outSize = partonSystemsPtr->sizeOut(0);
+                for (int iMem = 0; iMem < outSize; iMem++) {
+                  int iNow = partonSystemsPtr->getOut(0, iMem);
+                  
+                  // Coloured only, i != jNow and no carbon copies
+                  if (iNow == jNow || e[iNow].colType() == 0) continue;
+                  if (jNow == e[iNow].daughter1() 
+                      && jNow == e[iNow].daughter2()) continue;
+                  
+                  pTnow = pTpowheg(e, iNow, jNow, (pTdefMode == 0) 
+                                   ? false : FSR);
+                  if (pTnow > 0.) pTemt = (pTemt < 0) 
+                    ? pTnow : min(pTemt, pTnow);
+                } // for (iMem)
+                
+              } // if (!FSR)
+              
+              // Pythia
+            } else if (pTdefMode == 2) {
+              
+              // ISR - other incoming as recoiler
+              if (!FSR) {
+                pTnow = pTpythia(e, iInA, jNow, iInB, FSR);
+                if (pTnow > 0.) pTemt = (pTemt < 0) ? pTnow : min(pTemt, pTnow);
+                pTnow = pTpythia(e, iInB, jNow, iInA, FSR);
+                if (pTnow > 0.) pTemt = (pTemt < 0) ? pTnow : min(pTemt, pTnow);
+                
+                // FSR - try all final-state coloured partons as radiator
+                //       after emission (k).
+              } else {
+                for (int kNow = 0; kNow < e.size(); kNow++) {
+                  if (kNow == jNow || !e[kNow].isFinal() ||
+                      e[kNow].colType() == 0) continue;
+                  
+                  // For this kNow, need to have a recoiler.
+                  // Try two incoming.
+                  pTnow = pTpythia(e, kNow, jNow, iInA, FSR);
+                  if (pTnow > 0.) pTemt = (pTemt < 0) 
+                    ? pTnow : min(pTemt, pTnow);
+                  pTnow = pTpythia(e, kNow, jNow, iInB, FSR);
+                  if (pTnow > 0.) pTemt = (pTemt < 0) 
+                    ? pTnow : min(pTemt, pTnow);
+                  
+                  // Try all other outgoing.
+                  for (int rNow = 0; rNow < e.size(); rNow++) {
+                    if (rNow == kNow || rNow == jNow ||
+                        !e[rNow].isFinal() || e[rNow].colType() == 0) continue;
+                    pTnow = pTpythia(e, kNow, jNow, rNow, FSR);
+                    if (pTnow > 0.) pTemt = (pTemt < 0) 
+                      ? pTnow : min(pTemt, pTnow);
+                  } // for (rNow)
+                  
+                } // for (kNow)
+              } // if (!FSR)
+            } // if (pTdefMode)
+          } // for (j)
+        }
+      } // for (xSR)
+      
+#ifdef DBGOUTPUT
+      cout << "pTcalc: i = " << i << ", j = " << j << ", k = " << k
+      << ", r = " << r << ", xSR = " << xSRin
+      << ", pTemt = " << pTemt << endl;
+#endif
+      
+      return pTemt;
+    }
+    
+    //--------------------------------------------------------------------------
+    
+    // Extraction of pThard based on the incoming event.
+    // Assume that all the final-state particles are in a continuous block
+    // at the end of the event and the final entry is the POWHEG emission.
+    // If there is no POWHEG emission, then pThard is set to Qfac.
+    
+    bool canVetoMPIStep()    { return true; }
+    int  numberVetoMPIStep() { return 1; }
+    bool doVetoMPIStep(int nMPI, const Event &e) {
+      // Extra check on nMPI
+      if (nMPI > 1) return false;
+      
+      // Find if there is a POWHEG emission. Go backwards through the
+      // event record until there is a non-final particle. Also sum pT and
+      // find pT_1 for possible MPI vetoing
+      int    count = 0;
+      double pT1 = 0., pTsum = 0.;
+      for (int i = e.size() - 1; i > 0; i--) {
+        if (e[i].isFinal()) {
+          count++;
+          pT1    = e[i].pT();
+          pTsum += e[i].pT();
+        } else break;
+      }
+      // Extra check that we have the correct final state
+      if (count != nFinal && count != nFinal + 1) {
+        cout << "Error: wrong number of final state particles in event" << endl;
+        exit(1);
+      }
+      // Flag if POWHEG radiation present and index
+      bool isEmt = (count == nFinal) ? false : true;
+      int  iEmt  = (isEmt) ? e.size() - 1 : -1;
+      
+      // If there is no radiation or if pThardMode is 0 then set pThard to Qfac.
+      if (!isEmt || pThardMode == 0) {
+        pThard = infoPtr->QFac();
+        
+        // If pThardMode is 1 then the pT of the POWHEG emission is checked against
+        // all other incoming and outgoing partons, with the minimal value taken
+      } else if (pThardMode == 1) {
+        pThard = pTcalc(e, -1, iEmt, -1, -1, -1);
+        
+        // If pThardMode is 2, then the pT of all final-state partons is checked
+        // against all other incoming and outgoing partons, with the minimal value
+        // taken
+      } else if (pThardMode == 2) {
+        pThard = pTcalc(e, -1, -1, -1, -1, -1);
+        
+      }
+      
+      // Find MPI veto pT if necessary
+      if (MPIvetoMode == 1) {
+        pTMPI = (isEmt) ? pTsum / 2. : pT1;
+      }
+      
+#ifdef DBGOUTPUT
+      cout << "doVetoMPIStep: Qfac = " << infoPtr->QFac()
+      << ", pThard = " << pThard << endl << endl;
+#endif
+      
+//      std::cout<<"vetoScale = "<<pThard<<std::endl;
+      
+      // Initialise other variables
+      accepted   = false;
+      nAcceptSeq = nISRveto = nFSRveto = 0;
+      
+      // Do not veto the event
+      return false;
+    }
+    
+    //--------------------------------------------------------------------------
+    
+    // ISR veto
+    
+    bool canVetoISREmission() { return (vetoMode == 0) ? false : true; }
+    bool doVetoISREmission(int, const Event &e, int iSys) {
+      // Must be radiation from the hard system
+      if (iSys != 0) return false;
+      
+      // If we already have accepted 'vetoCount' emissions in a row, do nothing
+      if (vetoMode == 1 && nAcceptSeq >= vetoCount) return false;
+      
+      // Pythia radiator after, emitted and recoiler after.
+      int iRadAft = -1, iEmt = -1, iRecAft = -1;
+      for (int i = e.size() - 1; i > 0; i--) {
+        if      (iRadAft == -1 && e[i].status() == -41) iRadAft = i;
+        else if (iEmt    == -1 && e[i].status() ==  43) iEmt    = i;
+        else if (iRecAft == -1 && e[i].status() == -42) iRecAft = i;
+        if (iRadAft != -1 && iEmt != -1 && iRecAft != -1) break;
+      }
+      if (iRadAft == -1 || iEmt == -1 || iRecAft == -1) {
+        e.list();
+        cout << "Error: couldn't find Pythia ISR emission" << endl;
+        exit(1);
+      }
+      
+      // pTemtMode == 0: pT of emitted w.r.t. radiator
+      // pTemtMode == 1: min(pT of emitted w.r.t. all incoming/outgoing)
+      // pTemtMode == 2: min(pT of all outgoing w.r.t. all incoming/outgoing)
+      int xSR      = (pTemtMode == 0) ? 0       : -1;
+      int i        = (pTemtMode == 0) ? iRadAft : -1;
+      int j        = (pTemtMode != 2) ? iEmt    : -1;
+      int k        = -1;
+      int r        = (pTemtMode == 0) ? iRecAft : -1;
+      double pTemt = pTcalc(e, i, j, k, r, xSR);
+      
+#ifdef DBGOUTPUT
+      cout << "doVetoISREmission: pTemt = " << pTemt << endl << endl;
+#endif
+      
+      // Veto if pTemt > pThard
+      if (pTemt > pThard) {
+        nAcceptSeq = 0;
+        nISRveto++;
+        return true;
+      }
+      
+      // Else mark that an emission has been accepted and continue
+      nAcceptSeq++;
+      accepted = true;
+      return false;
+    }
+    
+    //--------------------------------------------------------------------------
+    
+    // FSR veto
+    
+    bool canVetoFSREmission() { return (vetoMode == 0) ? false : true; }
+    bool doVetoFSREmission(int, const Event &e, int iSys, bool) {
+      // Must be radiation from the hard system
+      if (iSys != 0) return false;
+      
+      // If we already have accepted 'vetoCount' emissions in a row, do nothing
+      if (vetoMode == 1 && nAcceptSeq >= vetoCount) return false;
+      
+      // Pythia radiator (before and after), emitted and recoiler (after)
+      int iRecAft = e.size() - 1;
+      int iEmt    = e.size() - 2;
+      int iRadAft = e.size() - 3;
+      int iRadBef = e[iEmt].mother1();
+      if ( (e[iRecAft].status() != 52 && e[iRecAft].status() != -53) ||
+          e[iEmt].status() != 51 || e[iRadAft].status() != 51) {
+        e.list();
+        cout << "Error: couldn't find Pythia FSR emission" << endl;
+        exit(1);
+      }
+      
+      // Behaviour based on pTemtMode:
+      //  0 - pT of emitted w.r.t. radiator before
+      //  1 - min(pT of emitted w.r.t. all incoming/outgoing)
+      //  2 - min(pT of all outgoing w.r.t. all incoming/outgoing)
+      int xSR = (pTemtMode == 0) ? 1       : -1;
+      int i   = (pTemtMode == 0) ? iRadBef : -1;
+      int k   = (pTemtMode == 0) ? iRadAft : -1;
+      int r   = (pTemtMode == 0) ? iRecAft : -1;
+      
+      // When pTemtMode is 0 or 1, iEmt has been selected
+      double pTemt = 0.;
+      if (pTemtMode == 0 || pTemtMode == 1) {
+        // Which parton is emitted, based on emittedMode:
+        //  0 - Pythia definition of emitted
+        //  1 - Pythia definition of radiated after emission
+        //  2 - Random selection of emitted or radiated after emission
+        //  3 - Try both emitted and radiated after emission
+        int j = iRadAft;
+        if (emittedMode == 0 || (emittedMode == 2 && rndmPtr->flat() < 0.5)) j++;
+        
+        for (int jLoop = 0; jLoop < 2; jLoop++) {
+          if      (jLoop == 0) pTemt = pTcalc(e, i, j, k, r, xSR);
+          else if (jLoop == 1) pTemt = min(pTemt, pTcalc(e, i, j, k, r, xSR));
+          
+          // For emittedMode == 3, have tried iRadAft, now try iEmt
+          if (emittedMode != 3) break;
+          if (k != -1) swap(j, k); else j = iEmt;
+        }
+        
+        // If pTemtMode is 2, then try all final-state partons as emitted
+      } else if (pTemtMode == 2) {
+        pTemt = pTcalc(e, i, -1, k, r, xSR);
+        
+      }
+      
+#ifdef DBGOUTPUT
+      cout << "doVetoFSREmission: pTemt = " << pTemt << endl << endl;
+#endif
+      
+      // Veto if pTemt > pThard
+      if (pTemt > pThard) {
+        nAcceptSeq = 0;
+        nFSRveto++;
+        return true;
+      }
+      
+      // Else mark that an emission has been accepted and continue
+      nAcceptSeq++;
+      accepted = true;
+      return false;
+    }
+    
+    //--------------------------------------------------------------------------
+    
+    // MPI veto
+    
+    bool canVetoMPIEmission() { return (MPIvetoMode == 0) ? false : true; }
+    bool doVetoMPIEmission(int, const Event &e) {
+      if (MPIvetoMode == 1) {
+        if (e[e.size() - 1].pT() > pTMPI) {
+#ifdef DBGOUTPUT
+          cout << "doVetoMPIEmission: pTnow = " << e[e.size() - 1].pT()
+          << ", pTMPI = " << pTMPI << endl << endl;
+#endif
+          return true;
+        }
+      }
+      return false;
+    }
+    
+    //--------------------------------------------------------------------------
+    
+    // Functions to return information
+    
+    int    getNISRveto() { return nISRveto; }
+    int    getNFSRveto() { return nFSRveto; }
+    
+  private:
+    int    nFinal, vetoMode, vetoCount, pThardMode, pTemtMode,
+    emittedMode, pTdefMode, MPIvetoMode;
+    double pThard, pTMPI;
+    bool   accepted;
+    // The number of accepted emissions (in a row)
+    int nAcceptSeq;
+    // Statistics on vetos
+    unsigned long int nISRveto, nFSRveto;
+    
+  };
+}
diff --git a/Generators/Pythia8_i/src/UserHooksFactory.cxx b/Generators/Pythia8_i/src/UserHooksFactory.cxx
new file mode 100644
index 00000000000..1bddd3c8c27
--- /dev/null
+++ b/Generators/Pythia8_i/src/UserHooksFactory.cxx
@@ -0,0 +1,27 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "Pythia8_i/UserHooksFactory.h"
+
+#include <stdexcept>
+
+namespace Pythia8_UserHooks{
+ 
+  UserHooks *UserHooksFactory::create(const string &name){
+    map<string, const ICreator*>::const_iterator it = s_creators().find(name);
+    if(it == s_creators().end()){
+      //eek!
+      throw std::runtime_error("Pythia 8 UserHooksFactory: cannot create user hook " + name);
+    }
+    return it->second->create();
+  }
+ 
+  ///static function to instantiate map of string name Vs. creator object on first use
+  map<string, const UserHooksFactory::ICreator*> &UserHooksFactory::s_creators(){
+    static map<string, const UserHooksFactory::ICreator*> creators;
+    return creators;
+  }
+  
+}
+
diff --git a/Generators/Pythia8_i/src/UserProcessFactory.cxx b/Generators/Pythia8_i/src/UserProcessFactory.cxx
new file mode 100644
index 00000000000..5dbacc6888b
--- /dev/null
+++ b/Generators/Pythia8_i/src/UserProcessFactory.cxx
@@ -0,0 +1,28 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "Pythia8_i/UserProcessFactory.h"
+
+#include <stdexcept>
+
+namespace Pythia8_UserProcess{
+ 
+  Sigma2Process *UserProcessFactory::create(const string &name){
+    map<string, const ICreator*>::const_iterator it = s_creators().find(name);
+    if(it == s_creators().end()){
+      //eek!
+      throw std::runtime_error("Pythia 8 UserProcessFactory: cannot create user process " + name);
+    }
+    
+    return it->second->create();
+  }
+  
+  ///static function to instantiate map of string name Vs. creator object on first use
+  map<string, const UserProcessFactory::ICreator*> &UserProcessFactory::s_creators(){
+    static map<string, const UserProcessFactory::ICreator*> creators;
+    return creators;
+  }
+  
+}
+
diff --git a/Generators/Pythia8_i/src/UserProcesses/Sigma2qqbar2emu.cxx b/Generators/Pythia8_i/src/UserProcesses/Sigma2qqbar2emu.cxx
new file mode 100644
index 00000000000..f9fb4b72e4d
--- /dev/null
+++ b/Generators/Pythia8_i/src/UserProcesses/Sigma2qqbar2emu.cxx
@@ -0,0 +1,127 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+/**
+ *  Lepton flavour violating differential cross sections
+ */
+
+#include "Pythia8_i/UserProcessFactory.h"
+
+// calls to fortran routines
+#include "CLHEP/Random/RandFlat.h"
+
+#include <iostream>
+#include <vector>
+
+namespace Pythia8{
+  class Sigma2qqbar2emu;
+}
+
+// This one line registers this process with the factory
+// An instance of this process can be created with 
+// UserProcessFactory::create("qqbar2emu")
+Pythia8_UserProcess::UserProcessFactory::Creator<Pythia8::Sigma2qqbar2emu> qqbar2emuCreator("qqbar2emu");
+
+namespace Pythia8 {
+  
+  /**
+   *
+   *  Sigma1ql2LFV class.
+   *  Cross section for q qbar -> e mu (t:squark).
+   */
+  
+  class Sigma2qqbar2emu : public Sigma2Process{
+    
+  public:
+    //Constructor.
+    Sigma2qqbar2emu()
+    : lambdaCoup(0.), sigmaTemp(0.), m_stop(0.),
+    lambdaSqddbar(0.), lambdaSqdsbar(0.), lambdaSqsdbar(0.), lambdaSqssbar(0.),
+    Nc(0), myRand(0) 
+    {}
+    
+    
+    /// Initialize process. 
+    void initProc() {
+      
+      // Store parameters.
+      lambdaCoup = 0.2;
+      Nc = 3;
+      m_stop = particleDataPtr->m0(1000006);   //95.5;
+      lambdaSqddbar = 0.065;
+      lambdaSqdsbar = 3.8e-5;
+      lambdaSqsdbar = 3.8e-5;
+      lambdaSqssbar = 0.065;
+      myRand = new Rndm(1234567);
+      
+      return;
+    } 
+    
+    //*********
+    
+    /// Evaluate sigmaHat(sHat), part independent of incoming flavour. 
+    void sigmaKin() {
+      
+      // The 2 out front is for e- mu+ plus e+ mu -
+      sigmaTemp = 2./((float)Nc * 64. * M_PI);
+      
+      return;
+    }
+    
+    //*********
+    
+    /// Evaluate sigmaHat(sHat), part dependent of incoming flavour. 
+    double sigmaHat() {
+      
+      double lambdaSq = 0.;
+      if((id1 == 1 && id2 == -1) || (id1 == -1 && id2 == 1)) lambdaSq = lambdaSqddbar;
+      else if((id1 == 1 && id2 == -3) || (id1 == -3 && id2 == 1)) lambdaSq = lambdaSqdsbar;
+      else if((id1 == 3 && id2 == -1) || (id1 == -1 && id2 == 3)) lambdaSq = lambdaSqsdbar;
+      else if((id1 == 3 && id2 == -3) || (id1 == -3 && id2 == 3)) lambdaSq = lambdaSqssbar;
+      double sigma = pow2(lambdaSq)*sigmaTemp*tH2/(sH2*pow2(tH-pow2(m_stop)));
+      return sigma;
+    }
+    
+    //*********
+    
+    // Select identity, colour and anticolour.
+    
+    void setIdColAcol() {
+      
+      // Flavours.
+      double x = myRand->flat();
+      if(x < 0.5) setId( id1, id2, 11, -13);
+      else setId( id1, id2, -11, 13);
+      
+      // tH defined between f and LQ: must swap tHat <-> uHat if qbar q in.
+      swapTU = (id1 < 0); 
+      
+      //cab I don't understand what's done here.
+      // Colour flow topologies.
+      if (id1 > 0) setColAcol( 1, 0, 0, 1, 0, 0, 0, 0);
+      else         setColAcol( 0, 1, 1, 0, 0, 0, 0, 0);
+      
+      return;
+    }
+    
+    // Info on the subprocess.
+    string name()    const {return "q qbar -> e mu (t:squark)";}
+    //cab Need Codes for q qbar -> e+- mu-+
+    int    code()    const {return 10001;}
+    string inFlux()  const {return "qq";}
+    //cab It looks like here is where the final state is specified
+    //cab electrons are +-11, muons are +-13
+    int    id3Mass() const {return 11;}
+    int    id4Mass() const {return 13;}
+    
+  private:
+    
+    // Parameters set at initialization or for current kinematics.
+    double lambdaCoup, sigmaTemp, m_stop;
+    double lambdaSqddbar, lambdaSqdsbar, lambdaSqsdbar, lambdaSqssbar;
+    int Nc;
+    Rndm* myRand;
+  
+  };
+}
diff --git a/Generators/Pythia8_i/src/UserProcesses/Sigma2qqbar2lStarlBar.cxx b/Generators/Pythia8_i/src/UserProcesses/Sigma2qqbar2lStarlBar.cxx
new file mode 100644
index 00000000000..b3d362e651c
--- /dev/null
+++ b/Generators/Pythia8_i/src/UserProcesses/Sigma2qqbar2lStarlBar.cxx
@@ -0,0 +1,187 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// Single excited lepton production  - similar to original pythia8 code, 
+// but polarization of final state is reversed [to match Calchep distributions
+
+#include "Pythia8_i/UserProcessFactory.h"
+
+#include <iostream>
+#include <vector>
+
+namespace Pythia8 {
+  class Sigma2qqbar2lStarlBar;
+  class Sigma2qqbar2nueStarnueBar;  
+  class Sigma2qqbar2numuStarnumuBar;
+  class Sigma2qqbar2nutauStarnutauBar;
+  class Sigma2qqbar2eStareBar;        
+  class Sigma2qqbar2muStarmuBar;      
+  class Sigma2qqbar2tauStartauBar;    
+}
+
+// This one line registers this process with the factory
+// An instance of this process can be created with 
+// UserProcessFactory::create("qqbar2lStarlBar")
+Pythia8_UserProcess::UserProcessFactory::Creator<Pythia8::Sigma2qqbar2nueStarnueBar>     qqbar2nueStarnueBarCreator(    "qqbar2nueStarnueBar");
+Pythia8_UserProcess::UserProcessFactory::Creator<Pythia8::Sigma2qqbar2numuStarnumuBar>   qqbar2numuStarnumuBarCreator(  "qqbar2numuStarnumuBar");
+Pythia8_UserProcess::UserProcessFactory::Creator<Pythia8::Sigma2qqbar2nutauStarnutauBar> qqbar2nutauStarnutauBarCreator("qqbar2nutauStarnutauBar");
+Pythia8_UserProcess::UserProcessFactory::Creator<Pythia8::Sigma2qqbar2eStareBar>         qqbar2eStareBarCreator(        "qqbar2eStareBar");
+Pythia8_UserProcess::UserProcessFactory::Creator<Pythia8::Sigma2qqbar2muStarmuBar>       qqbar2muStarmuBarCreator(      "qqbar2muStarmuBar");
+Pythia8_UserProcess::UserProcessFactory::Creator<Pythia8::Sigma2qqbar2tauStartauBar>     qqbar2tauStartauBarCreator(    "qqbar2tauStartauBar");
+
+namespace Pythia8 {
+  
+  //**************************************************************************
+  
+  // Sigma2qqbar2lStarlBar class.
+  // Cross section for q qbar -> lStar lBar
+  
+  class Sigma2qqbar2lStarlBar: public Sigma2Process {
+    
+  public:
+    //Constructor.
+    Sigma2qqbar2lStarlBar(int idlIn) : idl(idlIn),
+    idRes(0), codeSave(0),
+    Lambda(0.), preFac(0.), openFracPos(0.), openFracNeg(0.), sigma(0.), m2ResTimes4(0.){};
+    
+    //*********
+    
+    // Initialize process. 
+    
+    void initProc() {
+      
+      // Set up process properties from the chosen lepton flavour.
+      idRes         = 4000000 + idl;
+      codeSave      = 4060 + idl;
+      if      (idl == 11) nameSave = "q qbar -> e^*+- e^-+";
+      else if (idl == 12) nameSave = "q qbar -> nu_e^* nu_ebar"; 
+      else if (idl == 13) nameSave = "q qbar -> mu^*+- mu^-+"; 
+      else if (idl == 14) nameSave = "q qbar -> nu_mu^* nu_mubar"; 
+      else if (idl == 15) nameSave = "q qbar -> tau^*+- tau^-+"; 
+      else                nameSave = "q qbar -> nu_tau^* nu_taubar";
+      
+      // Secondary open width fractions.
+      openFracPos = particleDataPtr->resOpenFrac( idRes);
+      openFracNeg = particleDataPtr->resOpenFrac(-idRes);
+      
+      // Locally stored properties and couplings.
+      Lambda        = settingsPtr->parm("ExcitedFermion:Lambda");
+      preFac        = (M_PI / pow4(Lambda)) * (openFracPos + openFracNeg) / 3.; // orig pythia
+      //preFac        = (M_PI / pow4(Lambda)) * (openFracPos + openFracNeg) / 6.;
+      
+    } 
+    
+    //*********
+    // Evaluate sigmaHat(sHat). 
+    virtual double sigmaHat() {return sigma;}
+    
+    
+    // Evaluate sigmaHat(sHat), part independent of incoming flavour. 
+    
+    void sigmaKin() {
+      
+      // later this gets multiplied further with sH*(1-s3/sH)
+      
+      sigma = preFac * (-uH) * (sH + tH) / sH2;  // orig pythia
+      //sigma = preFac * (2. + s3/sH) *(1 - s3/sH) ;
+      //Baur sigma = preFac * ( 1 + 1./3.*(sH - s3)/(sH+s3) ) * (1 - s3/sH) * (1 + s3/sH);
+    }
+    
+    //*********
+    
+    // Select identity, colour and anticolour.
+    
+    void setIdColAcol() {
+      
+      // Flavours: either lepton or antilepton may be excited.
+      if (rndmPtr->flat() * (openFracPos + openFracNeg) < openFracPos) {
+        setId( id1, id2, idRes, -idl);
+        if (id1 < 0) swapTU = true; 
+      } else {
+        setId( id1, id2, -idRes, idl);
+        if (id1 > 0) swapTU = true; 
+      }  
+      
+      // Colour flow trivial.
+      if (id1 > 0) setColAcol( 1, 0, 0, 1, 0, 0, 0, 0);
+      else         setColAcol( 0, 1, 1, 0, 0, 0, 0, 0);
+      
+    }
+    
+    //**************************************************************************
+    
+    double weightDecay( Event& process, int iResBeg, 
+                       int iResEnd) {
+      
+      // l* should sit in entry 5. and 6 Sequential Z/W decay assumed isotropic.
+      if (iResBeg != 5 && iResEnd != 5 && iResBeg != 6 && iResEnd != 6 ) return 1.; 
+      
+      // Phase space factors.
+      double mr1    = pow2(process[7].m() / process[5].m());
+      double mr2    = pow2(process[8].m() / process[5].m()); 
+      
+      // Reconstruct decay angle in l* CoM frame.
+      int  idAbs3 = process[7].idAbs();
+      Vec4 pLStarCom = (idAbs3 < 20) ? process[8].p() : process[7].p();
+      //Vec4 pLStarCom = (idAbs3 < 20) ? process[7].p() : process[8].p(); // orig pythia
+      pLStarCom.bstback(process[5].p());
+      double cosThe = costheta(pLStarCom, process[5].p());
+      double wt     = 1.; 
+      
+      // Decay, l* -> l + gamma/Z^0/W^+-).
+      int idBoson   = (idAbs3 < 20) ? process[8].idAbs() : process[7].idAbs();
+      if (idBoson == 22) {
+        wt          = 0.5 * (1. + cosThe);
+      } else if (idBoson == 23 || idBoson == 24) {
+        double mrB  = (idAbs3 < 20) ? mr2 : mr1;
+        double kTrm = 0.5 * (mrB * (1. - cosThe));
+        wt          = (1. + cosThe + kTrm) / (2 + mrB);
+      } 
+      
+      // Done.
+      return wt;
+    }
+    
+    // Info on the subprocess.
+    virtual string name()       const {return nameSave;}
+    virtual int    code()       const {return codeSave;}
+    virtual string inFlux()     const {return "qqbarSame";}
+    virtual int    id3Mass()    const {return abs(idRes);}
+    
+    //virtual bool   convertM2()       const {return false;} //true is only suitable for resonance production pp->A->ll
+    //virtual bool   convert2mb()      const {return true;}
+    
+    // Parameters set at initialization or for current kinematics. 
+    int    idl, idRes, codeSave;
+    string nameSave;
+    double Lambda, preFac, openFracPos, openFracNeg, sigma;
+    double m2ResTimes4;
+  };
+  //**************************************************************************
+  class Sigma2qqbar2nueStarnueBar: public Sigma2qqbar2lStarlBar {
+  public:
+    Sigma2qqbar2nueStarnueBar() : Sigma2qqbar2lStarlBar(12) {}
+  };
+  class Sigma2qqbar2numuStarnumuBar: public Sigma2qqbar2lStarlBar {
+  public:
+    Sigma2qqbar2numuStarnumuBar() : Sigma2qqbar2lStarlBar(14) {}
+  };
+  class Sigma2qqbar2nutauStarnutauBar: public Sigma2qqbar2lStarlBar {
+  public:
+    Sigma2qqbar2nutauStarnutauBar() : Sigma2qqbar2lStarlBar(16) {}
+  };
+  class Sigma2qqbar2eStareBar: public Sigma2qqbar2lStarlBar {
+  public:
+    Sigma2qqbar2eStareBar() : Sigma2qqbar2lStarlBar(11) {}
+  };
+  class Sigma2qqbar2muStarmuBar: public Sigma2qqbar2lStarlBar {
+  public:
+    Sigma2qqbar2muStarmuBar() : Sigma2qqbar2lStarlBar(13) {}
+  };
+  class Sigma2qqbar2tauStartauBar: public Sigma2qqbar2lStarlBar {
+  public:
+    Sigma2qqbar2tauStartauBar() : Sigma2qqbar2lStarlBar(15) {}
+  };
+  
+}
diff --git a/Generators/Pythia8_i/src/UserProcesses/Sigma2qqbar2lStarlStarBar.cxx b/Generators/Pythia8_i/src/UserProcesses/Sigma2qqbar2lStarlStarBar.cxx
new file mode 100644
index 00000000000..02c0d32dfa6
--- /dev/null
+++ b/Generators/Pythia8_i/src/UserProcesses/Sigma2qqbar2lStarlStarBar.cxx
@@ -0,0 +1,186 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// Double excited lepton production
+
+#include "Pythia8_i/UserProcessFactory.h"
+
+#include <iostream>
+#include <vector>
+
+namespace Pythia8 {
+  class Sigma2qqbar2lStarlStarBar;
+  class Sigma2qqbar2nueStarnueStarBar;    
+  class Sigma2qqbar2numuStarnumuStarBar;  
+  class Sigma2qqbar2nutauStarnutauStarBar;
+  class Sigma2qqbar2eStareStarBar;        
+  class Sigma2qqbar2muStarmuStarBar;      
+  class Sigma2qqbar2tauStartauStarBar;    
+}
+
+// This one line registers this process with the factory
+// An instance of this process can be created with 
+// UserProcessFactory::create("qqbar2lStarlStarBar")
+Pythia8_UserProcess::UserProcessFactory::Creator<Pythia8::Sigma2qqbar2nueStarnueStarBar>     qqbar2nueStarlnuetarBarCreator(    "qqbar2nueStarnueStarBar");
+Pythia8_UserProcess::UserProcessFactory::Creator<Pythia8::Sigma2qqbar2numuStarnumuStarBar>   qqbar2numuStarlnumutarBarCreator(  "qqbar2numuStarnumuStarBar");
+Pythia8_UserProcess::UserProcessFactory::Creator<Pythia8::Sigma2qqbar2nutauStarnutauStarBar> qqbar2nutauStarlnutautarBarCreator("qqbar2nutauStarnutauStarBar");
+Pythia8_UserProcess::UserProcessFactory::Creator<Pythia8::Sigma2qqbar2eStareStarBar>         qqbar2eStarletarBarCreator(        "qqbar2eStareStarBar");
+Pythia8_UserProcess::UserProcessFactory::Creator<Pythia8::Sigma2qqbar2muStarmuStarBar>       qqbar2muStarlmutarBarCreator(      "qqbar2muStarmuStarBar");
+Pythia8_UserProcess::UserProcessFactory::Creator<Pythia8::Sigma2qqbar2tauStartauStarBar>     qqbar2tauStarltautarBarCreator(     "qqbar2tauStartauStarBar");
+
+namespace Pythia8 {
+  
+  //**************************************************************************
+  
+  // Sigma2qqbar2lStarlStarBar class.
+  // Cross section for q qbar -> lStar lStarBar
+  
+  // A derived class for q qbar -> lStar lStarBar
+  
+  class Sigma2qqbar2lStarlStarBar: public Sigma2Process {
+    
+  public:
+    //Constructor.
+    Sigma2qqbar2lStarlStarBar(int idlIn) : idl(idlIn),
+    idRes(0), codeSave(0),
+    Lambda(0.), preFac(0.), openFracPos(0.), openFracNeg(0.), sigma(0.),
+    m2ResTimes4(0.){};
+    
+    // Initialize process. 
+    
+    void initProc() {
+      
+      // Set up process properties from the chosen lepton flavour.
+      idRes         = 4000000 + idl;
+      codeSave      = 4040 + idl;
+      if      (idl == 11) nameSave = "q qbar -> e^*+- e^*-+";
+      else if (idl == 12) nameSave = "q qbar -> nu_e^* nu_e^*bar"; 
+      else if (idl == 13) nameSave = "q qbar -> mu^*+- mu^*-+"; 
+      else if (idl == 14) nameSave = "q qbar -> nu_mu^* nu_mu^*bar"; 
+      else if (idl == 15) nameSave = "q qbar -> tau^*+- tau^*-+"; 
+      else                nameSave = "q qbar -> nu_tau^* nu_tau^*bar";
+      
+      // Secondary open width fractions.
+      openFracPos = particleDataPtr->resOpenFrac( idRes);
+      openFracNeg = particleDataPtr->resOpenFrac(-idRes);
+      
+      // Locally stored properties and couplings.
+      Lambda        = settingsPtr->parm("ExcitedFermion:Lambda");
+      preFac        = (M_PI / pow4(Lambda)) * (openFracPos + openFracNeg) / 9.; 
+      
+      double mRes          = particleDataPtr->m0(idRes);
+      m2ResTimes4         = mRes*mRes*4.;
+    } 
+    
+    //*********
+    
+    // Evaluate sigmaHat(sHat). 
+    virtual double sigmaHat() {return sigma;}
+    
+    // Evaluate sigmaHat(sHat), part independent of incoming flavour. 
+    
+    void sigmaKin() {
+      
+      // use assumption that sigma is multiplied later with sH*(1-s3/sH)
+      
+      //sigma = preFac * sqrtpos( 1.- m2ResTimes4/sH );  
+      sigma = preFac * sqrtpos( 1.- 4.*s3/sH );  
+      
+    }
+    
+    //*********
+    
+    // Select identity, colour and anticolour.
+    
+    void setIdColAcol() {
+      
+      // Flavours: both lepton and antilepton are excited.
+      setId( id1, id2, idRes, -idRes);
+      //if (id1 < 0) swapTU = true;   // OI how is this used?
+      
+      // Colour flow trivial.  
+      if (id1 > 0) setColAcol( 1, 0, 0, 1, 0, 0, 0, 0);
+      else         setColAcol( 0, 1, 1, 0, 0, 0, 0, 0);
+      
+    }
+    
+    //**************************************************************************
+    
+    double weightDecay( Event& process, int iResBeg, 
+                       int iResEnd) {
+      
+      // l* should sit in entry 5. and 6 Sequential Z/W decay assumed isotropic.
+      if (iResBeg != 5 && iResEnd != 5 && iResBeg != 6 && iResEnd != 6 ) return 1.; 
+      
+      // Phase space factors.
+      double mr1    = pow2(process[7].m() / process[5].m());
+      double mr2    = pow2(process[8].m() / process[5].m()); 
+      
+      // Reconstruct decay angle in l* CoM frame.
+      int  idAbs3 = process[7].idAbs();
+      Vec4 pLStarCom = (idAbs3 < 20) ? process[8].p() : process[7].p();
+      pLStarCom.bstback(process[5].p());
+      double cosThe = costheta(pLStarCom, process[5].p());
+      double wt     = 1.; 
+      
+      // Decay, l* -> l + gamma/Z^0/W^+-).
+      int idBoson   = (idAbs3 < 20) ? process[8].idAbs() : process[7].idAbs();
+      if (idBoson == 22) {
+        wt          = 0.5 * (1. + cosThe);
+      } else if (idBoson == 23 || idBoson == 24) {
+        double mrB  = (idAbs3 < 20) ? mr2 : mr1;
+        double kTrm = 0.5 * (mrB * (1. - cosThe));
+        wt          = (1. + cosThe + kTrm) / (2 + mrB);
+      } 
+      
+      // Done.
+      return wt;
+    }
+    
+    // Info on the subprocess.
+    virtual string name()       const {return nameSave;}
+    virtual int    code()       const {return codeSave;}
+    virtual string inFlux()     const {return "qqbarSame";}
+    virtual int    id3Mass()    const {return abs(idRes);}
+    virtual int    id4Mass()    const {return abs(idRes);}
+    
+    virtual bool   convertM2()       const {return false;} //true is only suitable for resonance production pp->A->ll
+    virtual bool   convert2mb()      const {return true;}
+    
+    // Parameters set at initialization or for current kinematics. 
+    int    idl, idRes, codeSave;
+    string nameSave;
+    double Lambda, preFac, openFracPos, openFracNeg, sigma;
+    double m2ResTimes4;
+  };
+  
+  
+  //**************************************************************************
+  class Sigma2qqbar2nueStarnueStarBar: public Sigma2qqbar2lStarlStarBar {
+  public:
+    Sigma2qqbar2nueStarnueStarBar() : Sigma2qqbar2lStarlStarBar(12) {}
+  };
+  class Sigma2qqbar2numuStarnumuStarBar: public Sigma2qqbar2lStarlStarBar {
+  public:
+    Sigma2qqbar2numuStarnumuStarBar() : Sigma2qqbar2lStarlStarBar(14) {}
+  };
+  class Sigma2qqbar2nutauStarnutauStarBar: public Sigma2qqbar2lStarlStarBar {
+  public:
+    Sigma2qqbar2nutauStarnutauStarBar() : Sigma2qqbar2lStarlStarBar(16) {}
+  };
+  class Sigma2qqbar2eStareStarBar: public Sigma2qqbar2lStarlStarBar {
+  public:
+    Sigma2qqbar2eStareStarBar() : Sigma2qqbar2lStarlStarBar(11) {}
+  };
+  class Sigma2qqbar2muStarmuStarBar: public Sigma2qqbar2lStarlStarBar {
+  public:
+    Sigma2qqbar2muStarmuStarBar() : Sigma2qqbar2lStarlStarBar(13) {}
+  };
+  
+  class Sigma2qqbar2tauStartauStarBar: public Sigma2qqbar2lStarlStarBar {
+  public:
+    Sigma2qqbar2tauStartauStarBar() : Sigma2qqbar2lStarlStarBar(15) {}
+  };
+  
+}
diff --git a/Generators/Pythia8_i/src/UserResonanceFactory.cxx b/Generators/Pythia8_i/src/UserResonanceFactory.cxx
new file mode 100644
index 00000000000..04d513c862d
--- /dev/null
+++ b/Generators/Pythia8_i/src/UserResonanceFactory.cxx
@@ -0,0 +1,33 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+#include "Pythia8_i/UserResonanceFactory.h"
+
+#include <boost/lexical_cast.hpp>
+#include <boost/algorithm/string.hpp>
+
+#include <vector>
+#include <stdexcept>
+
+namespace Pythia8_UserResonance{
+
+  using std::vector;
+  
+  ResonanceWidths *UserResonanceFactory::create(const string &name, int pdgid){
+
+    map<string, const ICreator*>::const_iterator it = s_creators().find(name);
+    if(it == s_creators().end()){
+      //eek!
+      throw std::runtime_error("Pythia 8 UserResonanceFactory: cannot create user resonance " + name);
+    }
+    return it->second->create(pdgid);
+  }
+  
+  ///static function to instantiate map of string name Vs. creator object on first use
+  map<string, const UserResonanceFactory::ICreator*> &UserResonanceFactory::s_creators(){
+    static map<string, const UserResonanceFactory::ICreator*> creators;
+    return creators;
+  }
+  
+}
\ No newline at end of file
diff --git a/Generators/Pythia8_i/src/UserResonances/ResonanceExcitedCI.cxx b/Generators/Pythia8_i/src/UserResonances/ResonanceExcitedCI.cxx
new file mode 100644
index 00000000000..9d9a45f40f3
--- /dev/null
+++ b/Generators/Pythia8_i/src/UserResonances/ResonanceExcitedCI.cxx
@@ -0,0 +1,114 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+// The ResonanceExcited class handles excited-fermion resonances.
+// This is a copy of existing pythia ResonanceExcited class
+// with extention to include decays going via contact interactions (4-fermion vertexes)
+//
+// author Olya Igonkina, modified by James Monk for Pythia8_i
+
+#include "Pythia8_i/UserResonanceFactory.h"
+
+namespace Pythia8{
+  class ResonanceExcitedCI;
+}
+
+Pythia8_UserResonance::UserResonanceFactory::Creator<Pythia8::ResonanceExcitedCI> resonanceExcitedCreator("ExcitedCI");
+
+namespace Pythia8{
+  
+  class ResonanceExcitedCI : public ResonanceWidths {
+    
+  public:
+    
+    // Constructor. 
+    ResonanceExcitedCI(int idResIn):
+    m_lambda(0.), m_coupF(0.), m_coupFprime(0.), m_coupFcol(0.),
+    m_sin2tW(0.), m_cos2tW(0.){
+      initBasic(idResIn); std::cout << " ResonanceExcitedCI constructor\n"; 
+    } 
+    
+  private:
+    
+    void initConstants() {
+      
+      // Locally stored properties and couplings.
+      m_lambda        = settingsPtr->parm("ExcitedFermion:Lambda");
+      m_coupF         = settingsPtr->parm("ExcitedFermion:coupF");
+      m_coupFprime    = settingsPtr->parm("ExcitedFermion:coupFprime");
+      m_coupFcol      = settingsPtr->parm("ExcitedFermion:coupFcol");
+      m_sin2tW        = couplingsPtr->sin2thetaW();
+      m_cos2tW        = 1. - m_sin2tW;
+      
+      return;
+    }
+    
+    //--------------------------------------------------------------------------
+    
+    // Calculate various common prefactors for the current mass.
+    
+    void calcPreFac(bool) {
+      // Common coupling factors.
+      alpEM         = couplingsPtr->alphaEM(mHat * mHat);
+      alpS          = couplingsPtr->alphaS(mHat * mHat);
+      preFac        = pow3(mHat) / pow2(m_lambda);
+      
+      return;
+    }
+    
+    //--------------------------------------------------------------------------
+    
+    // Calculate width for currently considered channel.
+    
+    void calcWidth(bool) {
+      
+      // Check that above threshold.
+      if (ps == 0.) return;
+      
+      // f^* -> f g.
+      if (id1Abs == 21) widNow = preFac * alpS * pow2(m_coupFcol) / 3.;
+      
+      // f^* -> f gamma.
+      else if (id1Abs == 22) {
+        double chgI3 = (id2Abs%2 == 0) ? 0.5 : -0.5;
+        double chgY  = (id2Abs < 9) ? 1. / 6. : -0.5; 
+        double chg   = chgI3 * m_coupF + chgY * m_coupFprime;
+        widNow       = preFac * alpEM * pow2(chg) / 4.;      
+      }
+      // f^* -> f Z^0.
+      else if (id1Abs == 23) {
+        double chgI3 = (id2Abs%2 == 0) ? 0.5 : -0.5;
+        double chgY  = (id2Abs < 9) ? 1. / 6. : -0.5; 
+        double chg   = chgI3 * m_cos2tW * m_coupF - chgY * m_sin2tW * m_coupFprime;
+        widNow       = preFac * (alpEM * pow2(chg) / (8. * m_sin2tW * m_cos2tW))
+        * ps*ps * (2. + mr1);      
+      }
+      
+      // f^* -> f' W^+-.
+      else if (id1Abs == 24) widNow  = preFac * (alpEM * pow2(m_coupF) 
+                                                 / (16. * m_sin2tW)) * ps*ps * (2. + mr1);      
+      // idxAbs are sorted according to their abs value ; use idRes
+      
+      //  f^* -> f f' \bar{f'}
+      else {
+        //std::cout << " hei! in ResonanceExcitedCI processing F* -> f f'f'bar decays "<< id1Abs <<" "<<id2Abs<<" "<<id3Abs<< "\n";
+        
+        if( id1Abs < 17 && id2Abs < 17 && id3Abs>0 && id3Abs < 17 ){  // f* -> f f'\bar(f'} decay
+          widNow = preFac * pow2(mHat) / pow2(m_lambda) / 96. / M_PI ;
+          if( id3Abs < 10 ) widNow *= 3.; // quarks in final state. id1 is highest pdgId of f, f'
+          if( id1Abs == id2Abs && id1Abs == id3Abs ){
+            if( abs(idRes)-4000000 < 10 ) widNow *= 4./3.;  
+            else                          widNow *= 2.;
+          }
+        }
+      }
+     
+      return;
+    }
+    
+    // Locally stored properties and couplings.
+    double m_lambda, m_coupF, m_coupFprime, m_coupFcol, m_sin2tW, m_cos2tW;
+    
+  };
+}
diff --git a/Generators/Pythia8_i/src/components/Pythia8_i_entries.cxx b/Generators/Pythia8_i/src/components/Pythia8_i_entries.cxx
new file mode 100644
index 00000000000..562b20b314b
--- /dev/null
+++ b/Generators/Pythia8_i/src/components/Pythia8_i_entries.cxx
@@ -0,0 +1,11 @@
+#include "Pythia8_i/Pythia8_i.h"
+#include "GaudiKernel/DeclareFactoryEntries.h"
+
+/**
+ * author: James Monk (jmonk@hep.ucl.ac.uk)
+ */
+
+DECLARE_ALGORITHM_FACTORY( Pythia8_i )
+DECLARE_FACTORY_ENTRIES( Pythia8_i ){
+  DECLARE_ALGORITHM( Pythia8_i )
+}
diff --git a/Generators/Pythia8_i/src/components/Pythia8_i_load.cxx b/Generators/Pythia8_i/src/components/Pythia8_i_load.cxx
new file mode 100644
index 00000000000..4a1c8d8acff
--- /dev/null
+++ b/Generators/Pythia8_i/src/components/Pythia8_i_load.cxx
@@ -0,0 +1,7 @@
+#include "GaudiKernel/LoadFactoryEntries.h"
+
+/**
+ * author: James Monk (jmonk@hep.ucl.ac.uk)
+ */
+
+LOAD_FACTORY_ENTRIES( Pythia8_i )
-- 
GitLab