diff --git a/MatrixElement/Gamma/GammaGamma2PiPiAmplitude.cc b/MatrixElement/Gamma/GammaGamma2PiPiAmplitude.cc
new file mode 100644
--- /dev/null
+++ b/MatrixElement/Gamma/GammaGamma2PiPiAmplitude.cc
@@ -0,0 +1,171 @@
+// -*- C++ -*-
+//
+// This is the implementation of the non-inlined, non-templated member
+// functions of the GammaGamma2PiPiAmplitude class.
+//
+
+#include "GammaGamma2PiPiAmplitude.h"
+#include "ThePEG/Interface/ClassDocumentation.h"
+#include "ThePEG/Interface/Switch.h"
+#include "ThePEG/EventRecord/Particle.h"
+#include "ThePEG/Repository/UseRandom.h"
+#include "ThePEG/Repository/EventGenerator.h"
+#include "ThePEG/Utilities/DescribeClass.h"
+#include "ThePEG/Persistency/PersistentOStream.h"
+#include "ThePEG/Persistency/PersistentIStream.h"
+#include "ThePEG/Repository/EventGenerator.h"
+#include "ThePEG/Handlers/EventHandler.h"
+
+using namespace Herwig;
+
+IBPtr GammaGamma2PiPiAmplitude::clone() const {
+  return new_ptr(*this);
+}
+
+IBPtr GammaGamma2PiPiAmplitude::fullclone() const {
+  return new_ptr(*this);
+}
+
+void GammaGamma2PiPiAmplitude::persistentOutput(PersistentOStream & os) const {
+  os << mode_;
+}
+
+void GammaGamma2PiPiAmplitude::persistentInput(PersistentIStream & is , int) {
+  is >> mode_;
+}
+
+// The following static variable is needed for the type
+// description system in ThePEG.
+DescribeClass<GammaGamma2PiPiAmplitude,GammaGammaAmplitude>
+describeHerwigGammaGamma2PiPiAmplitude("Herwig::GammaGamma2PiPiAmplitude",
+				       "HwMEGammaGamma.so");
+
+void GammaGamma2PiPiAmplitude::Init() {
+
+  static ClassDocumentation<GammaGamma2PiPiAmplitude> documentation
+    ("The GammaGamma2PiPiAmplitude class implements the amplitude for gamma gamma -> pi+pi-");
+
+  
+  static Switch<GammaGamma2PiPiAmplitude,unsigned int> interfaceMode
+    ("Mode",
+     "Which particles to produce",
+     &GammaGamma2PiPiAmplitude::mode_, 0, false, false);
+  static SwitchOption interfaceModeAll
+    (interfaceMode,
+     "All",
+     "Produce all pions and kaons",
+     0);
+  static SwitchOption interfaceModePiPi
+    (interfaceMode,
+     "PiPi",
+     "Produce pi+pi-",
+     1);
+  static SwitchOption interfaceModeKK
+    (interfaceMode,
+     "KK",
+     "Produce K+K-",
+     2);
+
+}
+
+vector<DiagPtr> GammaGamma2PiPiAmplitude::getDiagrams(unsigned int iopt) const {
+  vector<DiagPtr> output;
+  output.reserve(2);
+  tcPDPtr gamma = getParticleData(ParticleID::gamma);
+  vector<long> ids; ids.reserve(2);
+  if(mode_==0 || mode_==1) ids.push_back(211);
+  if(mode_==0 || mode_==2) ids.push_back(321);
+  // gamma gamma process
+  if(iopt==0) {
+    // first t-channel
+    for (long id : ids) {
+      tcPDPtr pip = getParticleData(id);
+      tcPDPtr pim = pip->CC();
+      output.push_back(new_ptr((Tree2toNDiagram(3),gamma,pip,gamma,1,pip, 2,pim,-1)));
+      // interchange
+      output.push_back(new_ptr((Tree2toNDiagram(3),gamma,pip,gamma,2,pip, 1,pim,-2)));
+    }
+  }
+  // e+ e- > e+ e- pi+pi-
+  else {
+    cPDPair in = generator()->eventHandler()->incoming();
+    if(in.first->charged() && in.second->charged()) {
+      for (long id : ids) {
+	tcPDPtr pip = getParticleData(id);
+	tcPDPtr pim = pip->CC();
+	// first t-channel
+	output.push_back(new_ptr((Tree2toNDiagram(5),in.first,gamma,pip,gamma,in.second,
+				  1, in.first, 4, in.second, 2,pip, 3,pim,-1)));
+	// interchange
+	output.push_back(new_ptr((Tree2toNDiagram(5),in.first,gamma,pip,gamma,in.second,
+				  1, in.first, 4, in.second, 3,pip, 2,pim,-2)));
+      }
+    }
+  }
+  return output;
+}
+
+ProductionMatrixElement
+GammaGamma2PiPiAmplitude::helicityAmplitude(const vector<VectorWaveFunction> & v1,
+					    const vector<VectorWaveFunction> & v2,
+					    const vector<Lorentz5Momentum> & out,
+					    double & output,
+					    DVector & dweight) const {
+  dweight = {0.,0.};
+  vector<unsigned int> ihMax(4,0);
+  ProductionMatrixElement me = bookME(ihMax,v1.size(),v2.size(),vector<PDT::Spin>(2,PDT::Spin0));
+  // calculate the matrix element
+  Energy2 off = -0.5*v1[0].momentum().m2(); 
+  Energy2 d1  = off+v1[0].momentum()*out[0], d2 = off+v1[0].momentum()*out[1];
+  Complex diag[2];
+  for(unsigned int ih1A=0;ih1A<ihMax[0];++ih1A) {
+    for(unsigned int ih1B=0;ih1B<ihMax[1];++ih1B) {
+      unsigned int ih1 = 2*ih1A+ih1B;
+      complex<Energy> a1 = out[0]*v1[ih1].wave();
+      complex<Energy> a2 = out[1]*v1[ih1].wave();
+      for(unsigned int ih2A=0;ih2A<ihMax[2];++ih2A) {
+  	for(unsigned int ih2B=0;ih2B<ihMax[3];++ih2B) {
+	  unsigned int ih2 = 2*ih2A+ih2B;
+	  complex<Energy> b1 = out[0]*v2[ih2].wave();
+	  complex<Energy> b2 = out[1]*v2[ih2].wave();
+	  // t-channel diagram
+	  diag[0] = a1*b2/d1;
+	  // u-channel diagram
+	  diag[1] = a2*b1/d2;
+	  dweight[0] += norm(diag[0]);
+	  dweight[1] += norm(diag[1]);
+	  Complex amp = v1[ih1].wave()*v2[ih2].wave()-diag[0]-diag[1];
+	  output += norm(amp);
+	  if(v1.size()==2 && v2.size()==2)  me(2*ih1B,2*ih2B,0,0) = amp;
+	  else if(v1.size()==2)             me(2*ih1B,ih2A,ih2B,0,0) = amp;
+	  else if(v2.size()==2)             me(ih1A,ih1B,2*ih2B,0,0) = amp;
+	  else                              me(ih1A,ih1B,ih2A,ih2B,0,0) = amp;
+	}
+      }
+    }
+  }
+  return me;
+}
+
+
+double GammaGamma2PiPiAmplitude::me2(const vector<VectorWaveFunction> & v1,
+				     const vector<VectorWaveFunction> & v2,
+				     const Energy2 &, const Energy2 &,
+				     const Energy2 & , 
+				     const vector<Lorentz5Momentum> & out,
+				     const cPDVector &,
+				     DVector & dweights ) const {
+  // matrix element
+  double output(0.);
+  helicityAmplitude(v1,v2,out,output,dweights);
+  // prefactors
+  double alpha = generator()->standardModel()->alphaEM();
+  return output*sqr(alpha*4.*Constants::pi);
+}
+
+Energy GammaGamma2PiPiAmplitude::generateW(double r, const tcPDVector & partons, Energy Wmin, Energy Wmax,Energy2 & jacW, Energy2) {
+  Wmin = max(Wmin,2.*partons[0]->constituentMass());
+  Energy W = Wmin*pow(Wmax/Wmin,r);
+  jacW = 2.*sqr(W)*log(Wmax/Wmin);
+  return W;
+}
diff --git a/MatrixElement/Gamma/GammaGamma2PiPiAmplitude.h b/MatrixElement/Gamma/GammaGamma2PiPiAmplitude.h
new file mode 100644
--- /dev/null
+++ b/MatrixElement/Gamma/GammaGamma2PiPiAmplitude.h
@@ -0,0 +1,168 @@
+// -*- C++ -*-
+#ifndef Herwig_GammaGamma2PiPiAmplitude_H
+#define Herwig_GammaGamma2PiPiAmplitude_H
+//
+// This is the declaration of the GammaGamma2PiPiAmplitude class.
+//
+
+#include "GammaGammaAmplitude.h"
+#include "Herwig/Models/StandardModel/StandardModel.h"
+
+namespace Herwig {
+
+using namespace ThePEG;
+
+/**
+ * The GammaGamma2PiPiAmplitude class implements the amplitude for \f$\gamma\gamma\to\pi^+\pi^-\f$.
+ *
+ * @see \ref GammaGamma2PiPiAmplitudeInterfaces "The interfaces"
+ * defined for GammaGamma2PiPiAmplitude.
+ */
+class GammaGamma2PiPiAmplitude: public GammaGammaAmplitude {
+
+public:
+  
+  /**
+   * The default constructor.
+   */
+  GammaGamma2PiPiAmplitude() : mode_(0)
+  {}
+
+public:
+
+  /** @name Virtual functions required by GammaGammaAmplitude class. */
+  //@{
+  /**
+   * Return the order in \f$\alpha_S\f$ in which this matrix
+   * element is given.
+   */
+  virtual unsigned int orderInAlphaS() const {
+    return 0;
+  }
+
+  /**
+   * Return the order in \f$\alpha_{EW}\f$ in which this matrix
+   * element is given.
+   */
+  virtual unsigned int orderInAlphaEW() const {
+    return 2;
+  }
+
+  /**
+   * The number of internal degrees of freedom used in the matrix
+   * element.
+   */
+  virtual int nDim(unsigned int iopt) const {
+    return iopt+2;
+  }
+
+  /**
+   *  The Feynman diagrams (iopt=0 gamma gamma, iopt=1, e+e-)
+   */
+  virtual vector<DiagPtr> getDiagrams(unsigned int iopt) const;
+
+  /**
+   *  The matrix element
+   */
+  virtual double me2(const vector<VectorWaveFunction> & v1,
+		     const vector<VectorWaveFunction> & v2,
+		     const Energy2 & t1, const Energy2 & t2,
+		     const Energy2 & scale, 
+		     const vector<Lorentz5Momentum> & momenta,
+		     const cPDVector & partons,
+		     DVector & dweights ) const; 
+  
+  /**
+   * Matrix element for spin correlations
+   */
+  virtual ProductionMatrixElement me(const vector<VectorWaveFunction> & v1,
+				     const vector<VectorWaveFunction> & v2,
+				     tParticleVector & particles) const {
+    ScalarWaveFunction(particles[0],outgoing,true);
+    ScalarWaveFunction(particles[1],outgoing,true);
+    vector<Lorentz5Momentum> pout = {particles[0]->momentum(),
+				     particles[1]->momentum()};
+    double output(0);
+    DVector dwgt;
+    return helicityAmplitude(v1,v2,pout,output,dwgt);
+  }
+
+  /**
+   * Generate the mass of the \f$\gamma\gamma\f$ system
+   */
+  virtual Energy generateW(double , const tcPDVector & partons, Energy Wmin, Energy Wmax,Energy2 & jacW, Energy2 scale);
+  //@}
+
+public:
+
+  /** @name Functions used by the persistent I/O system. */
+  //@{
+  /**
+   * Function used to write out object persistently.
+   * @param os the persistent output stream written to.
+   */
+  void persistentOutput(PersistentOStream & os) const;
+
+  /**
+   * Function used to read in object persistently.
+   * @param is the persistent input stream read from.
+   * @param version the version number of the object when written.
+   */
+  void persistentInput(PersistentIStream & is, int version);
+  //@}
+
+  /**
+   * The standard Init function used to initialize the interfaces.
+   * Called exactly once for each class by the class description system
+   * before the main function starts or
+   * when this class is dynamically loaded.
+   */
+  static void Init();
+
+protected:
+
+  /** @name Clone Methods. */
+  //@{
+  /**
+   * Make a simple clone of this object.
+   * @return a pointer to the new object.
+   */
+  virtual IBPtr clone() const;
+
+  /** Make a clone of this object, possibly modifying the cloned object
+   * to make it sane.
+   * @return a pointer to the new object.
+   */
+  virtual IBPtr fullclone() const;
+  //@}
+
+protected:
+
+  /**
+   *  Calculation of the helicity amplitudes for the process
+   */
+  ProductionMatrixElement helicityAmplitude(const vector<VectorWaveFunction> & v1,
+					    const vector<VectorWaveFunction> & v2,
+					    const vector<Lorentz5Momentum> & out,
+					    double & output, DVector & dweights) const;
+
+private:
+
+  /**
+   * The assignment operator is private and must never be called.
+   * In fact, it should not even be implemented.
+   */
+  GammaGamma2PiPiAmplitude & operator=(const GammaGamma2PiPiAmplitude &) = delete;
+
+private:
+
+  /**
+   *   Which particles to produce
+   */
+  unsigned int mode_;
+
+};
+
+}
+
+#endif /* Herwig_GammaGamma2PiPiAmplitude_H */
diff --git a/MatrixElement/Gamma/GammaGamma2PseudoScalarAmplitude.cc b/MatrixElement/Gamma/GammaGamma2PseudoScalarAmplitude.cc
new file mode 100644
--- /dev/null
+++ b/MatrixElement/Gamma/GammaGamma2PseudoScalarAmplitude.cc
@@ -0,0 +1,177 @@
+// -*- C++ -*-
+//
+// This is the implementation of the non-inlined, non-templated member
+// functions of the GammaGamma2PseudoScalarAmplitude class.
+//
+
+#include "GammaGamma2PseudoScalarAmplitude.h"
+#include "ThePEG/Interface/ClassDocumentation.h"
+#include "ThePEG/Interface/Reference.h"
+#include "ThePEG/Interface/Switch.h"
+#include "ThePEG/Interface/Parameter.h"
+#include "ThePEG/EventRecord/Particle.h"
+#include "ThePEG/Repository/UseRandom.h"
+#include "ThePEG/Repository/EventGenerator.h"
+#include "ThePEG/Utilities/DescribeClass.h"
+#include "ThePEG/Persistency/PersistentOStream.h"
+#include "ThePEG/Persistency/PersistentIStream.h"
+#include "ThePEG/Helicity/epsilon.h"
+#include "ThePEG/Handlers/EventHandler.h"
+
+using namespace Herwig;
+
+IBPtr GammaGamma2PseudoScalarAmplitude::clone() const {
+  return new_ptr(*this);
+}
+
+IBPtr GammaGamma2PseudoScalarAmplitude::fullclone() const {
+  return new_ptr(*this);
+}
+
+void GammaGamma2PseudoScalarAmplitude::persistentOutput(PersistentOStream & os) const {
+  os << particle_ << ounit(FTT_,1./GeV) << ounit(LambdaP2_,GeV2) << mOpt_ << massGen_;
+}
+
+void GammaGamma2PseudoScalarAmplitude::persistentInput(PersistentIStream & is, int) {
+  is >> particle_ >> iunit(FTT_,1./GeV) >> iunit(LambdaP2_,GeV2) >> mOpt_ >> massGen_;
+}
+
+void GammaGamma2PseudoScalarAmplitude::doinit() {
+  GammaGammaAmplitude::doinit();
+  if(particle_->iSpin()!=PDT::Spin0)
+    throw Exception() << "Mustr have a spin-0 particle in GammaGamma2PseudoScalarAmplitude"
+		      << Exception::runerror;
+  if(particle_->massGenerator())
+    massGen_=dynamic_ptr_cast<GenericMassGeneratorPtr>(particle_->massGenerator());
+  if(!massGen_) mOpt_=0;
+}
+
+// The following static variable is needed for the type
+// description system in ThePEG.
+DescribeClass<GammaGamma2PseudoScalarAmplitude,GammaGammaAmplitude>
+describeHerwigGammaGamma2PseudoScalarAmplitude("Herwig::GammaGamma2PseudoScalarAmplitude",
+					       "HwMEGammaGamma.so");
+
+void GammaGamma2PseudoScalarAmplitude::Init() {
+
+  static ClassDocumentation<GammaGamma2PseudoScalarAmplitude> documentation
+    ("The GammaGamma2PseudoScalarAmplitude class implements"
+     " the amplitude for gamma gamma -> pseudoscalar");
+  
+  static Reference<GammaGamma2PseudoScalarAmplitude,ParticleData> interfaceParticle
+    ("Particle",
+     "The particle produced by the amplitude",
+     &GammaGamma2PseudoScalarAmplitude::particle_, false, false, true, false, false);
+
+  static Parameter<GammaGamma2PseudoScalarAmplitude,InvEnergy> interfaceFTT
+    ("FTT",
+     "The form factor at zero momentum transfer",
+     &GammaGamma2PseudoScalarAmplitude::FTT_, 1/GeV, 0.274/GeV, 0./GeV, 100./GeV,
+     false, false, Interface::limited);
+
+  static Parameter<GammaGamma2PseudoScalarAmplitude,Energy2> interfaceLambdaP2
+    ("LambdaP2",
+     "The square of the pole mass for the form factor",
+     &GammaGamma2PseudoScalarAmplitude::LambdaP2_, GeV2, 0.6*GeV2, 0.0*GeV2, 10.0*GeV2,
+     false, false, Interface::limited);
+  
+  static Switch<GammaGamma2PseudoScalarAmplitude,unsigned int> interfaceMassOption
+    ("MassOption",
+     "Option for the generation of the pseudoscalar mass",
+     &GammaGamma2PseudoScalarAmplitude::mOpt_, 0, false, false);
+  static SwitchOption interfaceMassOptionOnShell
+    (interfaceMassOption,
+     "OnShell",
+     "Generate the pseudoscalar state on-shell",
+     0);
+  static SwitchOption interfaceMassOptionOffShell
+    (interfaceMassOption,
+     "OffShell",
+     "Generate an off-shell pseudoscalar state using the mass generator",
+     1);
+
+}
+
+vector<DiagPtr> GammaGamma2PseudoScalarAmplitude::getDiagrams(unsigned int iopt) const {
+  vector<DiagPtr> output;
+  output.reserve(3);
+  tcPDPtr g  = getParticleData(ParticleID::gamma );
+  if(iopt==0) {
+    output.push_back(new_ptr((Tree2toNDiagram(2), g, g, 1, particle_, -1)));
+  }
+  else {
+    cPDPair in = generator()->eventHandler()->incoming();
+    if(in.first->charged() && in.second->charged())
+      output.push_back(new_ptr((Tree2toNDiagram(4), in.first, g, g, in.second,
+				1, in.first, 3, in.second, 2, particle_, -1)));
+  }
+  return output;
+}
+
+ProductionMatrixElement GammaGamma2PseudoScalarAmplitude::
+helicityAmplitude(const vector<VectorWaveFunction> & v1,
+		  const vector<VectorWaveFunction> & v2,
+		  const Energy & M, double & output) const {
+  vector<unsigned int> ihMax(4,0);
+  ProductionMatrixElement me = bookME(ihMax,v1.size(),v2.size(),vector<PDT::Spin>(1,PDT::Spin0));
+  // calculate the matrix element
+  output = 0;
+  Lorentz5Momentum pG1 = v1[0].momentum();
+  Lorentz5Momentum pG2 = v2[0].momentum();
+  for(unsigned int ih1A=0;ih1A<ihMax[0];++ih1A) {
+    for(unsigned int ih1B=0;ih1B<ihMax[1];++ih1B) {
+      auto vOff = Helicity::epsilon(v1[2*ih1A+ih1B].wave(),pG1,pG2);
+      for(unsigned int ih2A=0;ih2A<ihMax[2];++ih2A) {
+  	for(unsigned int ih2B=0;ih2B<ihMax[3];++ih2B) {
+  	  Complex amp = (vOff*v2[2*ih2A+ih2B].wave())/sqr(M);
+  	  output += norm(amp);
+	  if(v1.size()==2 && v2.size()==2)  me(2*ih1B,2*ih2B,0) = amp;
+	  else if(v1.size()==2)             me(2*ih1B,ih2A,ih2B,0) = amp;
+	  else if(v2.size()==2)             me(ih1A,ih1B,2*ih2B,0) = amp;
+	  else                              me(ih1A,ih1B,ih2A,ih2B,0) = amp;
+  	}
+      }
+    }
+  }
+  return me;
+}
+
+double GammaGamma2PseudoScalarAmplitude::me2(const vector<VectorWaveFunction> & v1,
+					     const vector<VectorWaveFunction> & v2,
+					     const Energy2 & t1, const Energy2 & t2,
+					     const Energy2 & scale, 
+					     const vector<Lorentz5Momentum> & momenta,
+					     const cPDVector & , DVector &  ) const {
+  Energy M  = momenta.back().mass();
+  // calculate the matrix element
+  double output(0.);
+  helicityAmplitude(v1,v2,M,output);
+  // form factor
+  InvEnergy form = FTT_/(1.-t1/LambdaP2_)/(1.-t2/LambdaP2_);
+  // coupling factors
+  double alpha = generator()->standardModel()->alphaEM();
+  return 0.25*pow<4,1>(M)/scale*sqr(form)*output*sqr(alpha*4.*Constants::pi);
+}
+
+Energy GammaGamma2PseudoScalarAmplitude::generateW(double r, const tcPDVector & partons, Energy Wmin,
+						   Energy Wmax,Energy2 & jacW, Energy2 scale) {
+  Wmin = max(Wmin,partons.back()->massMin());
+  Wmax = min(Wmax,partons.back()->massMax());
+  double wgt(0.);
+  Energy output = massGen_->mass(wgt,*partons.back(),Wmin,Wmax,r);
+  jacW = scale*wgt;
+  return output;
+}
+
+double GammaGamma2PseudoScalarAmplitude::
+generateKinematics(const double *,
+		   const Energy2 & scale, 
+		   vector<Lorentz5Momentum> & momenta,
+		   const tcPDVector & ) {
+  Energy M = sqrt(scale);
+  double jac = scale*massGen_->BreitWignerWeight(M)/pow(Constants::twopi,3);
+  momenta[0].setVect(Momentum3(ZERO,ZERO,ZERO));
+  momenta[0].setE(M);
+  momenta[0].rescaleMass();
+  return jac;
+}
diff --git a/MatrixElement/Gamma/GammaGamma2PseudoScalarAmplitude.h b/MatrixElement/Gamma/GammaGamma2PseudoScalarAmplitude.h
new file mode 100644
--- /dev/null
+++ b/MatrixElement/Gamma/GammaGamma2PseudoScalarAmplitude.h
@@ -0,0 +1,213 @@
+// -*- C++ -*-
+#ifndef Herwig_GammaGamma2PseudoScalarAmplitude_H
+#define Herwig_GammaGamma2PseudoScalarAmplitude_H
+//
+// This is the declaration of the GammaGamma2PseudoScalarAmplitude class.
+//
+
+#include "GammaGammaAmplitude.h"
+#include "Herwig/Models/StandardModel/StandardModel.h"
+#include "Herwig/PDT/GenericMassGenerator.h"
+
+namespace Herwig {
+
+using namespace ThePEG;
+
+/**
+ * The GammaGamma2PseudoScalarAmplitude class implements the amplitide for \f$\gamma\gamma\to\f$ pseudoscalar meson
+ *
+ * @see \ref GammaGamma2PseudoScalarAmplitudeInterfaces "The interfaces"
+ * defined for GammaGamma2PseudoScalarAmplitude.
+ */
+class GammaGamma2PseudoScalarAmplitude: public GammaGammaAmplitude {
+
+public:
+
+  /**
+   * The default constructor.
+   */
+  GammaGamma2PseudoScalarAmplitude() : FTT_(0.274/GeV), LambdaP2_(0.6*GeV2), mOpt_(0)
+  {}
+
+public:
+
+  /** @name Virtual functions required by GammaGammaAmplitude class. */
+  //@{
+  /**
+   * Return the order in \f$\alpha_S\f$ in which this matrix
+   * element is given.
+   */
+  virtual unsigned int orderInAlphaS() const {
+    return 0;
+  }
+
+  /**
+   * Return the order in \f$\alpha_{EW}\f$ in which this matrix
+   * element is given.
+   */
+  virtual unsigned int orderInAlphaEW() const {
+    return 2;
+  }
+
+  /**
+   * The number of internal degrees of freedom used in the matrix
+   * element.
+   */
+  virtual int nDim(unsigned int) const {
+    return mOpt_;
+  }
+
+  /**
+   *  The Feynman diagrams (iopt=0 gamma gamma, iopt=1, e+e-)
+   */
+  virtual vector<DiagPtr> getDiagrams(unsigned int iopt) const;
+
+  /**
+   *  The matrix element
+   */
+  virtual double me2(const vector<VectorWaveFunction> & v1,
+		     const vector<VectorWaveFunction> & v2,
+		     const Energy2 & t1, const Energy2 & t2,
+		     const Energy2 & scale, 
+		     const vector<Lorentz5Momentum> & momenta,
+		     const cPDVector & partons,
+		     DVector & dweights ) const; 
+  
+  /**
+   * Matrix element for spin correlations
+   */
+  virtual ProductionMatrixElement me(const vector<VectorWaveFunction> & v1,
+				     const vector<VectorWaveFunction> & v2,
+				     tParticleVector & particles) const {
+    ScalarWaveFunction(particles[0],outgoing,true);
+    double output(0);
+    return helicityAmplitude(v1,v2,particles[0]->mass(),output);
+  }
+
+  /**
+   * Generate the mass of the \f$\gamma\gamma\f$ system
+   */
+  virtual Energy generateW(double r, const tcPDVector & partons, Energy Wmin,
+			   Energy Wmax, Energy2 & jacW, Energy2 scale);
+
+  /**
+   * Generate internal degrees of freedom given 'nDim()' uniform
+   * random numbers in the interval ]0,1[. To help the phase space
+   * generator, the 'dSigHatDR()' should be a smooth function of these
+   * numbers, although this is not strictly necessary. Return
+   * false if the chosen points failed the kinematical cuts.
+   */
+  virtual double generateKinematics(const double * r,
+				    const Energy2 & scale, 
+				    vector<Lorentz5Momentum> & momenta,
+				    const tcPDVector & partons);
+
+public:
+
+  /** @name Functions used by the persistent I/O system. */
+  //@{
+  /**
+   * Function used to write out object persistently.
+   * @param os the persistent output stream written to.
+   */
+  void persistentOutput(PersistentOStream & os) const;
+
+  /**
+   * Function used to read in object persistently.
+   * @param is the persistent input stream read from.
+   * @param version the version number of the object when written.
+   */
+  void persistentInput(PersistentIStream & is, int version);
+  //@}
+
+  /**
+   * The standard Init function used to initialize the interfaces.
+   * Called exactly once for each class by the class description system
+   * before the main function starts or
+   * when this class is dynamically loaded.
+   */
+  static void Init();
+
+protected:
+
+  /** @name Clone Methods. */
+  //@{
+  /**
+   * Make a simple clone of this object.
+   * @return a pointer to the new object.
+   */
+  virtual IBPtr clone() const;
+
+  /** Make a clone of this object, possibly modifying the cloned object
+   * to make it sane.
+   * @return a pointer to the new object.
+   */
+  virtual IBPtr fullclone() const;
+  //@}
+
+protected:
+
+  /** @name Standard Interfaced functions. */
+  //@{
+  /**
+   * Initialize this object after the setup phase before saving an
+   * EventGenerator to disk.
+   * @throws InitException if object could not be initialized properly.
+   */
+  virtual void doinit();
+  //@}
+
+protected:
+
+  /**
+   *  Calculation of the helicity amplitudes for the process
+   */
+  ProductionMatrixElement helicityAmplitude(const vector<VectorWaveFunction> & v1,
+					    const vector<VectorWaveFunction> & v2,
+					    const Energy & M, double & output) const;
+  
+private:
+
+  /**
+   * The assignment operator is private and must never be called.
+   * In fact, it should not even be implemented.
+   */
+  GammaGamma2PseudoScalarAmplitude & operator=(const GammaGamma2PseudoScalarAmplitude &) = delete;
+
+private:
+
+  /**
+   *   Particle
+   */
+  PDPtr particle_;
+  
+  /**
+   *   Parameters for the form-factors
+   */
+  //@{
+  /**
+   *    Form factor at $Q_1^2=Q_2^2=0$
+   */
+  InvEnergy FTT_;
+  
+  /**
+   * Pole mass squared parameter for the form factors
+   */
+  Energy2 LambdaP2_;
+
+  /**
+   *  Option for the mass generation
+   */
+  unsigned int mOpt_;
+
+  /**
+   *  The mass generator for the onium state
+   */
+  GenericMassGeneratorPtr massGen_;
+  //@}
+
+};
+
+}
+
+#endif /* Herwig_GammaGamma2PseudoScalarAmplitude_H */
diff --git a/MatrixElement/Gamma/GammaGamma2ScalarAmplitude.cc b/MatrixElement/Gamma/GammaGamma2ScalarAmplitude.cc
new file mode 100644
--- /dev/null
+++ b/MatrixElement/Gamma/GammaGamma2ScalarAmplitude.cc
@@ -0,0 +1,182 @@
+// -*- C++ -*-
+//
+// This is the implementation of the non-inlined, non-templated member
+// functions of the GammaGamma2ScalarAmplitude class.
+//
+
+#include "GammaGamma2ScalarAmplitude.h"
+#include "ThePEG/Interface/ClassDocumentation.h"
+#include "ThePEG/Interface/Reference.h"
+#include "ThePEG/Interface/Switch.h"
+#include "ThePEG/Interface/Parameter.h"
+#include "ThePEG/EventRecord/Particle.h"
+#include "ThePEG/Repository/UseRandom.h"
+#include "ThePEG/Repository/EventGenerator.h"
+#include "ThePEG/Utilities/DescribeClass.h"
+#include "ThePEG/Persistency/PersistentOStream.h"
+#include "ThePEG/Persistency/PersistentIStream.h"
+#include "ThePEG/Helicity/epsilon.h"
+#include "ThePEG/Handlers/EventHandler.h"
+
+using namespace Herwig;
+
+IBPtr GammaGamma2ScalarAmplitude::clone() const {
+  return new_ptr(*this);
+}
+
+IBPtr GammaGamma2ScalarAmplitude::fullclone() const {
+  return new_ptr(*this);
+}
+
+void GammaGamma2ScalarAmplitude::persistentOutput(PersistentOStream & os) const {
+  os << particle_ << ounit(FTT_,GeV) << ounit(LambdaP2_,GeV2) << mOpt_ << massGen_;
+}
+
+void GammaGamma2ScalarAmplitude::persistentInput(PersistentIStream & is, int) {
+  is >> particle_ >> iunit(FTT_,GeV) >> iunit(LambdaP2_,GeV2) >> mOpt_ >> massGen_;
+}
+
+void GammaGamma2ScalarAmplitude::doinit() {
+  GammaGammaAmplitude::doinit();
+  if(particle_->iSpin()!=PDT::Spin0)
+    throw Exception() << "Must have a spin-0 particle in GammaGamma2ScalarAmplitude"
+		      << Exception::runerror;
+  if(particle_->massGenerator())
+    massGen_=dynamic_ptr_cast<GenericMassGeneratorPtr>(particle_->massGenerator());
+  if(!massGen_) mOpt_=0;
+}
+
+// The following static variable is needed for the type
+// description system in ThePEG.
+DescribeClass<GammaGamma2ScalarAmplitude,GammaGammaAmplitude>
+describeHerwigGammaGamma2ScalarAmplitude("Herwig::GammaGamma2ScalarAmplitude",
+					 "HwMEGammaGamma.so");
+
+void GammaGamma2ScalarAmplitude::Init() {
+
+  static ClassDocumentation<GammaGamma2ScalarAmplitude> documentation
+    ("The GammaGamma2ScalarAmplitude class implements"
+     " the amplitude for gamma gamma -> pseudoscalar");
+  
+  static Reference<GammaGamma2ScalarAmplitude,ParticleData> interfaceParticle
+    ("Particle",
+     "The particle produced by the amplitude",
+     &GammaGamma2ScalarAmplitude::particle_, false, false, true, false, false);
+
+  static Parameter<GammaGamma2ScalarAmplitude,Energy> interfaceFTT
+    ("FTT",
+     "The form factor at zero momentum transfer",
+     &GammaGamma2ScalarAmplitude::FTT_, GeV, 8.89*MeV, 0.*GeV, 100.*GeV,
+     false, false, Interface::limited);
+
+  static Parameter<GammaGamma2ScalarAmplitude,Energy2> interfaceLambdaP2
+    ("LambdaP2",
+     "The square of the pole mass for the form factor",
+     &GammaGamma2ScalarAmplitude::LambdaP2_, GeV2, 0.6*GeV2, 0.0*GeV2, 10.0*GeV2,
+     false, false, Interface::limited);
+  
+  static Switch<GammaGamma2ScalarAmplitude,unsigned int> interfaceMassOption
+    ("MassOption",
+     "Option for the generation of the scalar mass",
+     &GammaGamma2ScalarAmplitude::mOpt_, 1, false, false);
+  static SwitchOption interfaceMassOptionOnShell
+    (interfaceMassOption,
+     "OnShell",
+     "Generate the scalar state on-shell",
+     0);
+  static SwitchOption interfaceMassOptionOffShell
+    (interfaceMassOption,
+     "OffShell",
+     "Generate an off-shell scalar state using the mass generator",
+     1);
+
+}
+
+vector<DiagPtr> GammaGamma2ScalarAmplitude::getDiagrams(unsigned int iopt) const {
+  vector<DiagPtr> output;
+  output.reserve(3);
+  tcPDPtr g  = getParticleData(ParticleID::gamma );
+
+  if(iopt==0) {
+    output.push_back(new_ptr((Tree2toNDiagram(2), g, g, 1, particle_, -1)));
+  }
+  else {
+    cPDPair in = generator()->eventHandler()->incoming();
+    if(in.first->charged() && in.second->charged())
+      output.push_back(new_ptr((Tree2toNDiagram(4), in.first, g, g, in.second,
+				1, in.first, 3, in.second, 2, particle_, -1)));
+  }
+  return output;
+}
+
+ProductionMatrixElement GammaGamma2ScalarAmplitude::
+helicityAmplitude(const vector<VectorWaveFunction> & v1,
+		  const vector<VectorWaveFunction> & v2,
+		  const Energy2 & t1, const Energy2 & t2,
+		  const Energy &, double & output) const {
+  vector<unsigned int> ihMax(4,0);
+  ProductionMatrixElement me = bookME(ihMax,v1.size(),v2.size(),vector<PDT::Spin>(1,PDT::Spin0));
+  // calculate the matrix element
+  output = 0;
+  Lorentz5Momentum pG1 = v1[0].momentum();
+  Lorentz5Momentum pG2 = v2[0].momentum();
+  Energy2 p1p2=pG1*pG2;
+  Energy4 X = sqr(p1p2)-t1*t2;
+  for(unsigned int ih1A=0;ih1A<ihMax[0];++ih1A) {
+    for(unsigned int ih1B=0;ih1B<ihMax[1];++ih1B) {
+      complex<Energy> d1[2]={ v1[2*ih1A+ih1B].wave()*pG1, v1[2*ih1A+ih1B].wave()*pG2};
+      for(unsigned int ih2A=0;ih2A<ihMax[2];++ih2A) {
+      	for(unsigned int ih2B=0;ih2B<ihMax[3];++ih2B) {
+	  complex<Energy> d2[2]={ v2[2*ih2A+ih2B].wave()*pG1, v2[2*ih2A+ih2B].wave()*pG2};
+	  Complex amp = v1[2*ih1A+ih1B].wave()*v2[2*ih2A+ih2B].wave()
+	    + (-p1p2*(d1[1]*d2[0]+d1[0]*d2[1]) + t2*d1[0]*d2[0] + t1*d1[1]*d2[1])/X;
+	  output += norm(amp);
+	  if(v1.size()==2 && v2.size()==2)  me(2*ih1B,2*ih2B,0) = amp;
+	  else if(v1.size()==2)             me(2*ih1B,ih2A,ih2B,0) = amp;
+	  else if(v2.size()==2)             me(ih1A,ih1B,2*ih2B,0) = amp;
+	  else                              me(ih1A,ih1B,ih2A,ih2B,0) = amp;
+      	}
+      }
+    }
+  }
+  return me;
+}
+
+double GammaGamma2ScalarAmplitude::me2(const vector<VectorWaveFunction> & v1,
+					     const vector<VectorWaveFunction> & v2,
+					     const Energy2 & t1, const Energy2 & t2,
+					     const Energy2 & scale, 
+					     const vector<Lorentz5Momentum> & momenta,
+					     const cPDVector & , DVector &  ) const {
+  Energy M  = momenta.back().mass();
+  // calculate the matrix element
+  double output(0.);
+  helicityAmplitude(v1,v2,t1,t2,M,output);
+  // form factor
+  Energy form = FTT_/(1.-t1/LambdaP2_)/(1.-t2/LambdaP2_);
+  // // coupling factors
+  double alpha = generator()->standardModel()->alphaEM();
+  return 0.25*sqr(form)/scale*output*sqr(alpha*4.*Constants::pi);
+}
+
+Energy GammaGamma2ScalarAmplitude::generateW(double r, const tcPDVector & partons, Energy Wmin,
+					     Energy Wmax,Energy2 & jacW, Energy2 scale) {
+  Wmin = max(Wmin,partons.back()->massMin());
+  Wmax = min(Wmax,partons.back()->massMax());
+  double wgt(0.);
+  Energy output = massGen_->mass(wgt,*partons.back(),Wmin,Wmax,r);
+  jacW = scale*wgt;
+  return output;
+}
+
+double GammaGamma2ScalarAmplitude::generateKinematics(const double * ,
+						      const Energy2 & scale, 
+						      vector<Lorentz5Momentum> & momenta,
+						      const tcPDVector & ) {
+  Energy M = sqrt(scale);
+  double jac = scale*massGen_->BreitWignerWeight(M)/pow(Constants::twopi,3);
+  momenta[0].setVect(Momentum3(ZERO,ZERO,ZERO));
+  momenta[0].setE(M);
+  momenta[0].rescaleMass();
+  return jac;
+}
diff --git a/MatrixElement/Gamma/GammaGamma2ScalarAmplitude.h b/MatrixElement/Gamma/GammaGamma2ScalarAmplitude.h
new file mode 100644
--- /dev/null
+++ b/MatrixElement/Gamma/GammaGamma2ScalarAmplitude.h
@@ -0,0 +1,215 @@
+// -*- C++ -*-
+#ifndef Herwig_GammaGamma2ScalarAmplitude_H
+#define Herwig_GammaGamma2ScalarAmplitude_H
+//
+// This is the declaration of the GammaGamma2ScalarAmplitude class.
+//
+
+#include "GammaGammaAmplitude.h"
+#include "Herwig/Models/StandardModel/StandardModel.h"
+#include "Herwig/PDT/GenericMassGenerator.h"
+
+namespace Herwig {
+
+using namespace ThePEG;
+
+/**
+ * The GammaGamma2ScalarAmplitude class implements the amplitide for \f$\gamma\gamma\to\f$ scalar meson
+ *
+ * @see \ref GammaGamma2ScalarAmplitudeInterfaces "The interfaces"
+ * defined for GammaGamma2ScalarAmplitude.
+ */
+class GammaGamma2ScalarAmplitude: public GammaGammaAmplitude {
+
+public:
+
+  /**
+   * The default constructor.
+   */
+  GammaGamma2ScalarAmplitude() : FTT_(8.89*MeV), LambdaP2_(0.6*GeV2), mOpt_(1)
+  {}
+
+public:
+
+  /** @name Virtual functions required by GammaGammaAmplitude class. */
+  //@{
+  /**
+   * Return the order in \f$\alpha_S\f$ in which this matrix
+   * element is given.
+   */
+  virtual unsigned int orderInAlphaS() const {
+    return 0;
+  }
+
+  /**
+   * Return the order in \f$\alpha_{EW}\f$ in which this matrix
+   * element is given.
+   */
+  virtual unsigned int orderInAlphaEW() const {
+    return 2;
+  }
+
+  /**
+   * The number of internal degrees of freedom used in the matrix
+   * element.
+   */
+  virtual int nDim(unsigned int) const {
+    return mOpt_;
+  }
+
+  /**
+   *  The Feynman diagrams (iopt=0 gamma gamma, iopt=1, e+e-)
+   */
+  virtual vector<DiagPtr> getDiagrams(unsigned int iopt) const;
+
+  /**
+   *  The matrix element
+   */
+  virtual double me2(const vector<VectorWaveFunction> & v1,
+		     const vector<VectorWaveFunction> & v2,
+		     const Energy2 & t1, const Energy2 & t2,
+		     const Energy2 & scale, 
+		     const vector<Lorentz5Momentum> & momenta,
+		     const cPDVector & partons,
+		     DVector & dweights ) const; 
+  
+  /**
+   * Matrix element for spin correlations
+   */
+  virtual ProductionMatrixElement me(const vector<VectorWaveFunction> & v1,
+				     const vector<VectorWaveFunction> & v2,
+				     tParticleVector & particles) const {
+    ScalarWaveFunction(particles[0],outgoing,true);
+    double output(0);
+    return helicityAmplitude(v1,v2,v1[0].momentum().m2(),v2[0].momentum().m2(),
+			     particles[0]->mass(),output);
+  }
+
+  /**
+   * Generate the mass of the \f$\gamma\gamma\f$ system
+   */
+  virtual Energy generateW(double r, const tcPDVector & partons, Energy Wmin,
+			   Energy Wmax, Energy2 & jacW, Energy2 scale);
+
+  /**
+   * Generate internal degrees of freedom given 'nDim()' uniform
+   * random numbers in the interval ]0,1[. To help the phase space
+   * generator, the 'dSigHatDR()' should be a smooth function of these
+   * numbers, although this is not strictly necessary. Return
+   * false if the chosen points failed the kinematical cuts.
+   */
+  virtual double generateKinematics(const double * r,
+				    const Energy2 & scale, 
+				    vector<Lorentz5Momentum> & momenta,
+				    const tcPDVector & partons);
+
+public:
+
+  /** @name Functions used by the persistent I/O system. */
+  //@{
+  /**
+   * Function used to write out object persistently.
+   * @param os the persistent output stream written to.
+   */
+  void persistentOutput(PersistentOStream & os) const;
+
+  /**
+   * Function used to read in object persistently.
+   * @param is the persistent input stream read from.
+   * @param version the version number of the object when written.
+   */
+  void persistentInput(PersistentIStream & is, int version);
+  //@}
+
+  /**
+   * The standard Init function used to initialize the interfaces.
+   * Called exactly once for each class by the class description system
+   * before the main function starts or
+   * when this class is dynamically loaded.
+   */
+  static void Init();
+
+protected:
+
+  /** @name Clone Methods. */
+  //@{
+  /**
+   * Make a simple clone of this object.
+   * @return a pointer to the new object.
+   */
+  virtual IBPtr clone() const;
+
+  /** Make a clone of this object, possibly modifying the cloned object
+   * to make it sane.
+   * @return a pointer to the new object.
+   */
+  virtual IBPtr fullclone() const;
+  //@}
+
+protected:
+
+  /** @name Standard Interfaced functions. */
+  //@{
+  /**
+   * Initialize this object after the setup phase before saving an
+   * EventGenerator to disk.
+   * @throws InitException if object could not be initialized properly.
+   */
+  virtual void doinit();
+  //@}
+
+protected:
+
+  /**
+   *  Calculation of the helicity amplitudes for the process
+   */
+  ProductionMatrixElement helicityAmplitude(const vector<VectorWaveFunction> & v1,
+					    const vector<VectorWaveFunction> & v2,
+					    const Energy2 & t1, const Energy2 & t2,
+					    const Energy & M, double & output) const;
+  
+private:
+
+  /**
+   * The assignment operator is private and must never be called.
+   * In fact, it should not even be implemented.
+   */
+  GammaGamma2ScalarAmplitude & operator=(const GammaGamma2ScalarAmplitude &) = delete;
+
+private:
+
+  /**
+   *   Particle
+   */
+  PDPtr particle_;
+  
+  /**
+   *   Parameters for the form-factors
+   */
+  //@{
+  /**
+   *    Form factor at $Q_1^2=Q_2^2=0$
+   */
+  Energy FTT_;
+  
+  /**
+   * Pole mass squared parameter for the form factors
+   */
+  Energy2 LambdaP2_;
+
+  /**
+   *  Option for the mass generation
+   */
+  unsigned int mOpt_;
+
+  /**
+   *  The mass generator for the onium state
+   */
+  GenericMassGeneratorPtr massGen_;
+  //@}
+
+};
+
+}
+
+#endif /* Herwig_GammaGamma2ScalarAmplitude_H */
diff --git a/MatrixElement/Gamma/GammaGamma2TensorAmplitude.cc b/MatrixElement/Gamma/GammaGamma2TensorAmplitude.cc
new file mode 100644
--- /dev/null
+++ b/MatrixElement/Gamma/GammaGamma2TensorAmplitude.cc
@@ -0,0 +1,201 @@
+// -*- C++ -*-
+//
+// This is the implementation of the non-inlined, non-templated member
+// functions of the GammaGamma2TensorAmplitude class.
+//
+
+#include "GammaGamma2TensorAmplitude.h"
+#include "ThePEG/Interface/ClassDocumentation.h"
+#include "ThePEG/Interface/Reference.h"
+#include "ThePEG/Interface/Switch.h"
+#include "ThePEG/Interface/Parameter.h"
+#include "ThePEG/EventRecord/Particle.h"
+#include "ThePEG/Repository/UseRandom.h"
+#include "ThePEG/Repository/EventGenerator.h"
+#include "ThePEG/Utilities/DescribeClass.h"
+#include "ThePEG/Persistency/PersistentOStream.h"
+#include "ThePEG/Persistency/PersistentIStream.h"
+#include "ThePEG/Helicity/epsilon.h"
+#include "ThePEG/Handlers/EventHandler.h"
+
+using namespace Herwig;
+
+IBPtr GammaGamma2TensorAmplitude::clone() const {
+  return new_ptr(*this);
+}
+
+IBPtr GammaGamma2TensorAmplitude::fullclone() const {
+  return new_ptr(*this);
+}
+
+void GammaGamma2TensorAmplitude::persistentOutput(PersistentOStream & os) const {
+  os << particle_ << ounit(FTT0_,1./GeV) << ounit(FTT2_,GeV) << ounit(LambdaP2_,GeV2) << mOpt_ << massGen_;
+}
+
+void GammaGamma2TensorAmplitude::persistentInput(PersistentIStream & is, int) {
+  is >> particle_ >> iunit(FTT0_,1./GeV) >> iunit(FTT2_,GeV) >> iunit(LambdaP2_,GeV2) >> mOpt_ >> massGen_;
+}
+
+void GammaGamma2TensorAmplitude::doinit() {
+  GammaGammaAmplitude::doinit();
+  if(particle_->iSpin()!=PDT::Spin2)
+    throw Exception() << "Mustr have a spin-2 particle in GammaGamma2TensorAmplitude"
+		      << Exception::runerror;
+  if(particle_->massGenerator())
+    massGen_=dynamic_ptr_cast<GenericMassGeneratorPtr>(particle_->massGenerator());
+  if(!massGen_) mOpt_=0;
+}
+
+// The following static variable is needed for the type
+// description system in ThePEG.
+DescribeClass<GammaGamma2TensorAmplitude,GammaGammaAmplitude>
+describeHerwigGammaGamma2TensorAmplitude("Herwig::GammaGamma2TensorAmplitude",
+					       "HwMEGammaGamma.so");
+
+void GammaGamma2TensorAmplitude::Init() {
+
+  static ClassDocumentation<GammaGamma2TensorAmplitude> documentation
+    ("The GammaGamma2TensorAmplitude class implements"
+     " the amplitude for gamma gamma -> pseudoscalar");
+  
+  static Reference<GammaGamma2TensorAmplitude,ParticleData> interfaceParticle
+    ("Particle",
+     "The particle produced by the amplitude",
+     &GammaGamma2TensorAmplitude::particle_, false, false, true, false, false);
+
+  static Parameter<GammaGamma2TensorAmplitude,InvEnergy> interfaceFTT0
+    ("FTT0",
+     "The form factor at zero momentum transfer",
+     &GammaGamma2TensorAmplitude::FTT0_, 1./GeV, 8.89/MeV, 0./GeV, 100./GeV,
+     false, false, Interface::limited);
+
+  static Parameter<GammaGamma2TensorAmplitude,Energy> interfaceFTT2
+    ("FTT2",
+     "The form factor at zero momentum transfer",
+     &GammaGamma2TensorAmplitude::FTT2_, GeV, 8.89*MeV, 0.*GeV, 100.*GeV,
+     false, false, Interface::limited);
+
+  static Parameter<GammaGamma2TensorAmplitude,Energy2> interfaceLambdaP2
+    ("LambdaP2",
+     "The square of the pole mass for the form factor",
+     &GammaGamma2TensorAmplitude::LambdaP2_, GeV2, 0.6*GeV2, 0.0*GeV2, 10.0*GeV2,
+     false, false, Interface::limited);
+  
+  static Switch<GammaGamma2TensorAmplitude,unsigned int> interfaceMassOption
+    ("MassOption",
+     "Option for the generation of the scalar mass",
+     &GammaGamma2TensorAmplitude::mOpt_, 1, false, false);
+  static SwitchOption interfaceMassOptionOnShell
+    (interfaceMassOption,
+     "OnShell",
+     "Generate the scalar state on-shell",
+     0);
+  static SwitchOption interfaceMassOptionOffShell
+    (interfaceMassOption,
+     "OffShell",
+     "Generate an off-shell scalar state using the mass generator",
+     1);
+
+}
+
+vector<DiagPtr> GammaGamma2TensorAmplitude::getDiagrams(unsigned int iopt) const {
+  vector<DiagPtr> output;
+  output.reserve(3);
+  tcPDPtr g  = getParticleData(ParticleID::gamma );
+
+  if(iopt==0) {
+    output.push_back(new_ptr((Tree2toNDiagram(2), g, g, 1, particle_, -1)));
+  }
+  else {
+    cPDPair in = generator()->eventHandler()->incoming();
+    if(in.first->charged() && in.second->charged())
+      output.push_back(new_ptr((Tree2toNDiagram(4), in.first, g, g, in.second,
+				1, in.first, 3, in.second, 2, particle_, -1)));
+  }
+  return output;
+}
+
+ProductionMatrixElement GammaGamma2TensorAmplitude::
+helicityAmplitude(const vector<VectorWaveFunction> & v1,
+		  const vector<VectorWaveFunction> & v2,
+		  const vector<TensorWaveFunction> & ten,
+		  const Energy2 & t1, const Energy2 & t2,
+		  const Energy & M, double & output) const {
+  vector<unsigned int> ihMax(4,0);
+  ProductionMatrixElement me = bookME(ihMax,v1.size(),v2.size(),vector<PDT::Spin>(1,PDT::Spin2));
+  // calculate the matrix element
+  output = 0;
+  Lorentz5Momentum pG1 = v1[0].momentum();
+  Lorentz5Momentum pG2 = v2[0].momentum();
+  Energy2 p1p2=pG1*pG2;
+  Energy4 X = sqr(p1p2)-t1*t2;
+  Lorentz5Momentum pDiff=pG1-pG2;
+  for(unsigned int ih1A=0;ih1A<ihMax[0];++ih1A) {
+    for(unsigned int ih1B=0;ih1B<ihMax[1];++ih1B) {
+      complex<Energy> d1[2]={ v1[2*ih1A+ih1B].wave()*pG1, v1[2*ih1A+ih1B].wave()*pG2};
+      LorentzPolarizationVector Q1 = (t1*pG2-p1p2*pG1)*d1[1]/X+v1[2*ih1A+ih1B].wave();
+      for(unsigned int ih2A=0;ih2A<ihMax[2];++ih2A) {
+     	for(unsigned int ih2B=0;ih2B<ihMax[2];++ih2B) {
+	  complex<Energy> d2[2]={ v2[2*ih2A+ih2B].wave()*pG1, v2[2*ih2A+ih2B].wave()*pG2};
+	  LorentzPolarizationVector Q2 = (t2*pG1-p1p2*pG2)*d2[0]/X+v2[2*ih2A+ih2B].wave();
+	  Complex amp0 = v1[2*ih1A+ih1B].wave()*v2[2*ih2A+ih2B].wave()
+	    + (-p1p2*(d1[1]*d2[0]+d1[0]*d2[1]) + t2*d1[0]*d2[0] + t1*d1[1]*d2[1])/X;
+	  for(unsigned int ih3=0;ih3<5;++ih3) {
+	    Complex amp = FTT0_*amp0/M*ten[ih3].wave().preDot(pDiff)*pDiff
+	      +FTT2_/M*ten[ih3].wave().preDot(Q1)*Q2;
+	    output += norm(amp);
+	    if(v1.size()==2 && v2.size()==2)  me(2*ih1B,2*ih2B,ih3) = amp;
+	    else if(v1.size()==2)             me(2*ih1B,ih2A,ih2B,ih3) = amp;
+	    else if(v2.size()==2)             me(ih1A,ih1B,2*ih2B,ih3) = amp;
+	    else                              me(ih1A,ih1B,ih2A,ih2B,ih3) = amp;
+	  }
+      	}
+      }
+    }
+  }
+  return me;
+}
+
+double GammaGamma2TensorAmplitude::me2(const vector<VectorWaveFunction> & v1,
+				       const vector<VectorWaveFunction> & v2,
+				       const Energy2 & t1, const Energy2 & t2,
+				       const Energy2 & scale, 
+				       const vector<Lorentz5Momentum> & momenta,
+				       const cPDVector & partons, DVector &  ) const {
+  Energy M  = momenta.back().mass();
+  // wavefunction for the tensor meson
+  vector<TensorWaveFunction> twave(5);
+  for(unsigned int i=0;i<5;++i) {
+    twave[i] = TensorWaveFunction(momenta.back(), partons.back(),i,outgoing);
+  }
+  // calculate the matrix element
+  double output(0.);
+  helicityAmplitude(v1,v2,twave,t1,t2,M,output);
+  // form factor
+  double form = 1./(1.-t1/LambdaP2_)/(1.-t2/LambdaP2_);
+  // coupling factors
+  double alpha = generator()->standardModel()->alphaEM();
+  return 0.25*sqr(M*form)/scale*output*sqr(alpha*4.*Constants::pi);
+}
+
+Energy GammaGamma2TensorAmplitude::generateW(double r, const tcPDVector & partons, Energy Wmin,
+					     Energy Wmax,Energy2 & jacW, Energy2 scale) {
+  Wmin = max(Wmin,partons.back()->massMin());
+  Wmax = min(Wmax,partons.back()->massMax());
+  double wgt(0.);
+  Energy output = massGen_->mass(wgt,*partons.back(),Wmin,Wmax,r);
+  jacW = scale*wgt;
+  return output;
+}
+
+double GammaGamma2TensorAmplitude::generateKinematics(const double * ,
+						      const Energy2 & scale, 
+						      vector<Lorentz5Momentum> & momenta,
+						      const tcPDVector & ) {
+  Energy M = sqrt(scale);
+  double jac = scale*massGen_->BreitWignerWeight(M)/pow(Constants::twopi,3);
+  momenta[0].setVect(Momentum3(ZERO,ZERO,ZERO));
+  momenta[0].setE(M);
+  momenta[0].rescaleMass();
+  return jac;
+}
diff --git a/MatrixElement/Gamma/GammaGamma2TensorAmplitude.h b/MatrixElement/Gamma/GammaGamma2TensorAmplitude.h
new file mode 100644
--- /dev/null
+++ b/MatrixElement/Gamma/GammaGamma2TensorAmplitude.h
@@ -0,0 +1,223 @@
+// -*- C++ -*-
+#ifndef Herwig_GammaGamma2TensorAmplitude_H
+#define Herwig_GammaGamma2TensorAmplitude_H
+//
+// This is the declaration of the GammaGamma2TensorAmplitude class.
+//
+
+#include "GammaGammaAmplitude.h"
+#include "Herwig/Models/StandardModel/StandardModel.h"
+#include "Herwig/PDT/GenericMassGenerator.h"
+#include "ThePEG/Helicity/WaveFunction/TensorWaveFunction.h"
+
+namespace Herwig {
+
+using namespace ThePEG;
+
+/**
+ * The GammaGamma2TensorAmplitude class implements the amplitide for \f$\gamma\gamma\to\f$ scalar meson
+ *
+ * @see \ref GammaGamma2TensorAmplitudeInterfaces "The interfaces"
+ * defined for GammaGamma2TensorAmplitude.
+ */
+class GammaGamma2TensorAmplitude: public GammaGammaAmplitude {
+
+public:
+
+  /**
+   * The default constructor.
+   */
+  GammaGamma2TensorAmplitude() : FTT0_(ZERO), FTT2_(8.89*MeV), LambdaP2_(0.6*GeV2), mOpt_(1)
+  {}
+
+public:
+
+  /** @name Virtual functions required by GammaGammaAmplitude class. */
+  //@{
+  /**
+   * Return the order in \f$\alpha_S\f$ in which this matrix
+   * element is given.
+   */
+  virtual unsigned int orderInAlphaS() const {
+    return 0;
+  }
+
+  /**
+   * Return the order in \f$\alpha_{EW}\f$ in which this matrix
+   * element is given.
+   */
+  virtual unsigned int orderInAlphaEW() const {
+    return 2;
+  }
+
+  /**
+   * The number of internal degrees of freedom used in the matrix
+   * element.
+   */
+  virtual int nDim(unsigned int) const {
+    return mOpt_;
+  }
+
+  /**
+   *  The Feynman diagrams (iopt=0 gamma gamma, iopt=1, e+e-)
+   */
+  virtual vector<DiagPtr> getDiagrams(unsigned int iopt) const;
+
+  /**
+   *  The matrix element
+   */
+  virtual double me2(const vector<VectorWaveFunction> & v1,
+		     const vector<VectorWaveFunction> & v2,
+		     const Energy2 & t1, const Energy2 & t2,
+		     const Energy2 & scale, 
+		     const vector<Lorentz5Momentum> & momenta,
+		     const cPDVector & partons,
+		     DVector & dweights ) const; 
+  
+  /**
+   * Matrix element for spin correlations
+   */
+  virtual ProductionMatrixElement me(const vector<VectorWaveFunction> & v1,
+				     const vector<VectorWaveFunction> & v2,
+				     tParticleVector & particles) const {
+    vector<TensorWaveFunction> t3;
+    TensorWaveFunction(t3,particles[0],outgoing,true,false);
+    double output(0);
+    return helicityAmplitude(v1,v2,t3,v1[0].momentum().m2(),v2[0].momentum().m2(),
+    			     particles[0]->mass(),output);
+  }
+
+  /**
+   * Generate the mass of the \f$\gamma\gamma\f$ system
+   */
+  virtual Energy generateW(double r, const tcPDVector & partons, Energy Wmin,
+			   Energy Wmax, Energy2 & jacW, Energy2 scale);
+
+  /**
+   * Generate internal degrees of freedom given 'nDim()' uniform
+   * random numbers in the interval ]0,1[. To help the phase space
+   * generator, the 'dSigHatDR()' should be a smooth function of these
+   * numbers, although this is not strictly necessary. Return
+   * false if the chosen points failed the kinematical cuts.
+   */
+  virtual double generateKinematics(const double * r,
+				    const Energy2 & scale, 
+				    vector<Lorentz5Momentum> & momenta,
+				    const tcPDVector & partons);
+
+public:
+
+  /** @name Functions used by the persistent I/O system. */
+  //@{
+  /**
+   * Function used to write out object persistently.
+   * @param os the persistent output stream written to.
+   */
+  void persistentOutput(PersistentOStream & os) const;
+
+  /**
+   * Function used to read in object persistently.
+   * @param is the persistent input stream read from.
+   * @param version the version number of the object when written.
+   */
+  void persistentInput(PersistentIStream & is, int version);
+  //@}
+
+  /**
+   * The standard Init function used to initialize the interfaces.
+   * Called exactly once for each class by the class description system
+   * before the main function starts or
+   * when this class is dynamically loaded.
+   */
+  static void Init();
+
+protected:
+
+  /** @name Clone Methods. */
+  //@{
+  /**
+   * Make a simple clone of this object.
+   * @return a pointer to the new object.
+   */
+  virtual IBPtr clone() const;
+
+  /** Make a clone of this object, possibly modifying the cloned object
+   * to make it sane.
+   * @return a pointer to the new object.
+   */
+  virtual IBPtr fullclone() const;
+  //@}
+
+protected:
+
+  /** @name Standard Interfaced functions. */
+  //@{
+  /**
+   * Initialize this object after the setup phase before saving an
+   * EventGenerator to disk.
+   * @throws InitException if object could not be initialized properly.
+   */
+  virtual void doinit();
+  //@}
+
+protected:
+
+  /**
+   *  Calculation of the helicity amplitudes for the process
+   */
+  ProductionMatrixElement helicityAmplitude(const vector<VectorWaveFunction> & v1,
+					    const vector<VectorWaveFunction> & v2,
+					    const vector<TensorWaveFunction> & ten,
+					    const Energy2 & t1, const Energy2 & t2,
+					    const Energy & M, double & output) const;
+  
+private:
+
+  /**
+   * The assignment operator is private and must never be called.
+   * In fact, it should not even be implemented.
+   */
+  GammaGamma2TensorAmplitude & operator=(const GammaGamma2TensorAmplitude &) = delete;
+
+private:
+
+  /**
+   *   Particle
+   */
+  PDPtr particle_;
+  
+  /**
+   *   Parameters for the form-factors
+   */
+  //@{
+  /**
+   *    Form factor at $Q_1^2=Q_2^2=0$
+   */
+  InvEnergy FTT0_;
+  
+  /**
+   *    Form factor at $Q_1^2=Q_2^2=0$
+   */
+  Energy FTT2_;
+  
+  /**
+   * Pole mass squared parameter for the form factors
+   */
+  Energy2 LambdaP2_;
+
+  /**
+   *  Option for the mass generation
+   */
+  unsigned int mOpt_;
+
+  /**
+   *  The mass generator for the onium state
+   */
+  GenericMassGeneratorPtr massGen_;
+  //@}
+
+};
+
+}
+
+#endif /* Herwig_GammaGamma2TensorAmplitude_H */
diff --git a/MatrixElement/Gamma/GammaGamma2ffAmplitude.cc b/MatrixElement/Gamma/GammaGamma2ffAmplitude.cc
new file mode 100644
--- /dev/null
+++ b/MatrixElement/Gamma/GammaGamma2ffAmplitude.cc
@@ -0,0 +1,284 @@
+// -*- C++ -*-
+//
+// This is the implementation of the non-inlined, non-templated member
+// functions of the GammaGamma2ffAmplitude class.
+//
+
+#include "GammaGamma2ffAmplitude.h"
+#include "ThePEG/Interface/ClassDocumentation.h"
+#include "ThePEG/EventRecord/Particle.h"
+#include "ThePEG/Repository/UseRandom.h"
+#include "ThePEG/Repository/EventGenerator.h"
+#include "ThePEG/Utilities/DescribeClass.h"
+#include "ThePEG/Interface/Switch.h"
+#include "ThePEG/Persistency/PersistentOStream.h"
+#include "ThePEG/Persistency/PersistentIStream.h"
+#include "Herwig/Models/StandardModel/StandardModel.h"
+#include "ThePEG/Handlers/EventHandler.h"
+
+using namespace Herwig;
+
+IBPtr GammaGamma2ffAmplitude::clone() const {
+  return new_ptr(*this);
+}
+
+IBPtr GammaGamma2ffAmplitude::fullclone() const {
+  return new_ptr(*this);
+}
+
+void GammaGamma2ffAmplitude::persistentOutput(PersistentOStream & os) const {
+  os << process_ << vertex_;
+}
+
+void GammaGamma2ffAmplitude::persistentInput(PersistentIStream & is, int) {
+  is >> process_ >> vertex_;
+}
+
+
+// The following static variable is needed for the type
+// description system in ThePEG.
+DescribeClass<GammaGamma2ffAmplitude,GammaGammaAmplitude>
+describeHerwigGammaGamma2ffAmplitude("Herwig::GammaGamma2ffAmplitude", "HwMEGammaGamma.so");
+
+void GammaGamma2ffAmplitude::Init() {
+
+  static ClassDocumentation<GammaGamma2ffAmplitude> documentation
+    ("The GammaGamma2ffAmplitude class implements the amplitude for gamma gamma -> f fbar");
+
+  static Switch<GammaGamma2ffAmplitude,int> interfaceProcess
+    ("Process",
+     "Which process to included",
+     &GammaGamma2ffAmplitude::process_, 0, false, false);
+  static SwitchOption interfaceProcessAll
+    (interfaceProcess,
+     "All",
+     "Include all SM fermions as outgoing particles",
+     0);
+  static SwitchOption interfaceProcessQuarks
+    (interfaceProcess,
+     "Quarks",
+     "All include the quarks as outgoing particles",
+     1);
+  static SwitchOption interfaceProcessLeptons
+    (interfaceProcess,
+     "Leptons",
+     "Only include the leptons as outgoing particles",
+     2);
+  static SwitchOption interfaceProcessElectron
+    (interfaceProcess,
+     "Electron",
+     "Only include e+e- as outgoing particles",
+     5);
+  static SwitchOption interfaceProcessMuon
+    (interfaceProcess,
+     "Muon",
+     "Only include mu+mu- as outgoing particles",
+     6);
+  static SwitchOption interfaceProcessTau
+    (interfaceProcess,
+     "Tau",
+     "Only include tau+tau- as outgoing particles",
+     7);
+  static SwitchOption interfaceProcessDown
+    (interfaceProcess,
+     "Down",
+     "Only include d dbar as outgoing particles",
+     11);
+  static SwitchOption interfaceProcessUp
+    (interfaceProcess,
+     "Up",
+     "Only include u ubar as outgoing particles",
+     12);
+  static SwitchOption interfaceProcessStrange
+    (interfaceProcess,
+     "Strange",
+     "Only include s sbar as outgoing particles",
+     13);
+  static SwitchOption interfaceProcessCharm
+    (interfaceProcess,
+     "Charm",
+     "Only include c cbar as outgoing particles",
+     14);
+  static SwitchOption interfaceProcessBottom
+    (interfaceProcess,
+     "Bottom",
+     "Only include b bbar as outgoing particles",
+     15);
+  static SwitchOption interfaceProcessTop
+    (interfaceProcess,
+     "Top",
+     "Only include t tbar as outgoing particles",
+     16);
+
+}
+
+vector<DiagPtr> GammaGamma2ffAmplitude::getDiagrams(unsigned int iopt) const {
+  vector<DiagPtr> output; output.reserve(24);
+  tcPDPtr gamma = getParticleData(ParticleID::gamma);
+  for(int ix=1;ix<17;++ix) {
+    // increment counter to switch between quarks and leptons
+    if(ix==7) ix+=4;
+    if(ix>11&&ix%2==0) ++ix;
+    // is it a valid quark process
+    bool quark = ix<=6 && (process_==0 || process_==1 || process_-10==ix);
+    // is it a valid lepton process
+    bool lepton= ix>=11 && ix<=16 && 
+      (process_==0 || process_==2 || ( (ix-9)/2 ==process_-4) );
+    // only add diagram if allowed
+    if(!quark && !lepton) continue;
+    tcPDPtr lm = getParticleData(ix);
+    tcPDPtr lp = lm->CC();
+    if(iopt==0) {
+      // first t-channel
+      output.push_back(new_ptr((Tree2toNDiagram(3),gamma,lp,gamma,1,lm, 2,lp,-1)));
+      // interchange
+      output.push_back(new_ptr((Tree2toNDiagram(3),gamma,lp,gamma,2,lm, 1,lp,-2)));
+    }
+    else {
+      cPDPair in = generator()->eventHandler()->incoming();
+      if(in.first->charged() && in.second->charged()) {
+	// first t-channel
+	output.push_back(new_ptr((Tree2toNDiagram(5),in.first,gamma,lp,gamma,in.second,
+				  1, in.first, 4, in.second, 2,lm, 3,lp,-1)));
+	// interchange
+	output.push_back(new_ptr((Tree2toNDiagram(5),in.first,gamma,lp,gamma,in.second,
+				  1, in.first, 4, in.second, 3,lm, 2,lp,-2)));
+      }
+    }
+  }
+  return output;
+}
+
+ProductionMatrixElement
+GammaGamma2ffAmplitude::helicityAmplitude(const vector<VectorWaveFunction> & v1,
+					  const vector<VectorWaveFunction> & v2,
+					  const vector<SpinorBarWaveFunction> & f,
+					  const vector<SpinorWaveFunction>    & fbar,
+					  double & output, DVector & dweight) const {
+  dweight = {0.,0.};
+  vector<unsigned int> ihMax(4,0);
+  ProductionMatrixElement me = bookME(ihMax,v1.size(),v2.size(),vector<PDT::Spin>(2,PDT::Spin1Half));
+  Complex diag[2];
+  Energy2 mt(ZERO);
+  SpinorWaveFunction inters;
+  for(unsigned int ih1A=0;ih1A<ihMax[0];++ih1A) {
+    for(unsigned int ih1B=0;ih1B<ihMax[1];++ih1B) {
+      unsigned int ih1 = 2*ih1A+ih1B;
+      for(unsigned int ih2A=0;ih2A<ihMax[2];++ih2A) {
+  	for(unsigned int ih2B=0;ih2B<ihMax[3];++ih2B) {
+	  unsigned int ih2 = 2*ih2A+ih2B;
+	  for(unsigned int ohel1=0;ohel1<2;++ohel1) { 
+	    for(unsigned int ohel2=0;ohel2<2;++ohel2) {
+	      // first t-channel diagram
+	      inters =vertex_->evaluate(mt,1,fbar[ohel2].particle()->CC(),
+					fbar[ohel2],v2[ih2]);
+	      diag[0]=vertex_->evaluate(mt,inters,f[ohel1],v1[ih1]);
+	      //second t-channel diagram
+	      inters =vertex_->evaluate(mt,1,fbar[ohel2].particle()->CC(),
+					fbar[ohel2],v1[ih1]);
+	      diag[1]=vertex_->evaluate(mt,inters,f[ohel1],v2[ih2]);
+	      dweight[0] += norm(diag[0]);
+	      dweight[1] += norm(diag[1]);
+	      Complex amp = diag[0]+diag[1];
+	      output += norm(amp);
+	      if(v1.size()==2 && v2.size()==2)  me(2*ih1B,2*ih2B,ohel1,ohel2) = amp;
+	      else if(v1.size()==2)             me(2*ih1B,ih2A,ih2B,ohel1,ohel2) = amp;
+	      else if(v2.size()==2)             me(ih1A,ih1B,2*ih2B,ohel1,ohel2) = amp;
+	      else                              me(ih1A,ih1B,ih2A,ih2B,ohel1,ohel2) = amp;
+	    }
+	  }
+	}
+      }
+    }
+  }
+  return me;
+}
+
+double GammaGamma2ffAmplitude::me2(const vector<VectorWaveFunction> & v1,
+				   const vector<VectorWaveFunction> & v2,
+				   const Energy2 & , const Energy2 & ,
+				   const Energy2 & , 
+				   const vector<Lorentz5Momentum> & momenta,
+				   const cPDVector & partons,
+				   DVector & sumdiag) const {
+  SpinorBarWaveFunction    fw(momenta[0],partons[0],outgoing);
+  SpinorWaveFunction    fbarw(momenta[1],partons[1],outgoing);
+  vector<SpinorBarWaveFunction> f;
+  vector<SpinorWaveFunction> fbar;
+  for(unsigned int ix=0;ix<2;++ix) {
+    fw.reset(ix);f.push_back(fw);
+    fbarw.reset(ix);fbar.push_back(fbarw);
+  }
+  // calculate the matrix element
+  double output(0.);
+  helicityAmplitude(v1,v2,f,fbar,output,sumdiag);
+  // colour factors if needed
+  if(partons[0]->coloured()) output *= 3.;
+  // // code to test vs the analytic result
+  // Energy2 m2 = sqr(f[0].particle()->mass());
+  // Energy2 tm = (v1[0].momentum()+f   [0].momentum()).m2()-m2;
+  // Energy2 um = (v1[0].momentum()+fbar[0].momentum()).m2()-m2;
+  // double test = 8.*um/tm+8.*tm/um- 32*m2/tm - 32*m2/um
+  //   -32*sqr(double(m2/tm)) - 64*sqr(m2)/tm/um - 32*sqr(double(m2/um));
+  // test *= sqr(4.*Constants::pi*SM().alphaEM());
+  // if(mePartonData()[2]->coloured()) test *= 3.;
+  // cerr << "testing ME " << (output-test)/(output+test) << "\n"; 
+  // spin factors
+  return 0.25*output;
+}
+
+void GammaGamma2ffAmplitude::doinit() {
+  GammaGammaAmplitude::doinit();
+  // cast the SM pointer to the Herwig SM pointer
+  tcHwSMPtr hwsm=ThePEG::dynamic_ptr_cast<tcHwSMPtr>(generator()->standardModel());
+  // do the initialisation
+  if(!hwsm)
+    throw InitException() << "Must be the Herwig StandardModel class in "
+ 			  << "MEGammaGamma2ff::doinit" << Exception::abortnow;
+  vertex_ = hwsm->vertexFFP();
+}
+
+Selector<const ColourLines *>
+GammaGamma2ffAmplitude::colourGeometries(unsigned int iopt, const cPDVector & partons, tcDiagPtr ) const {
+  static ColourLines c1("");
+  static ColourLines c2("4 -2 -5"); 
+  static ColourLines c3("8 -3 -9"); 
+  Selector<const ColourLines *> sel;
+  if(iopt==0) {
+    if(partons[2]->coloured()) sel.insert(1.0, &c2);
+    else                       sel.insert(1.0, &c1);
+  }
+  else {
+    if(partons[4]->coloured()) sel.insert(1.0, &c3);
+    else                       sel.insert(1.0, &c1);
+  }
+  return sel;
+}
+
+// MEGammaGamma2ff::MEGammaGamma2ff()  {
+//   massOption(vector<unsigned int>(2,1));
+// }
+
+// Energy2 MEGammaGamma2ff::scale() const {
+//   return 2.*sHat()*tHat()*uHat()/(sqr(sHat())+sqr(tHat())+sqr(uHat()));
+// }
+
+ProductionMatrixElement GammaGamma2ffAmplitude::me(const vector<VectorWaveFunction> & v1,
+						   const vector<VectorWaveFunction> & v2,
+						   tParticleVector & particles) const {
+  vector<SpinorWaveFunction> fbar;
+  vector<SpinorBarWaveFunction>  f;
+  SpinorBarWaveFunction(f   ,particles[0],outgoing,true );
+  SpinorWaveFunction   (fbar,particles[1],outgoing,true );
+  DVector dwgt;
+  double output(0);
+  return helicityAmplitude(v1,v2,f,fbar,output,dwgt);
+}
+
+Energy GammaGamma2ffAmplitude::generateW(double r, const tcPDVector & partons, Energy Wmin, Energy Wmax,Energy2 & jacW, Energy2) {
+  Wmin = max(Wmin,2.*partons[0]->constituentMass());
+  //Energy Wmin=3.*GeV;
+  Energy W = Wmin*pow(Wmax/Wmin,r);
+  jacW = 2.*sqr(W)*log(Wmax/Wmin);
+  return W;
+}
diff --git a/MatrixElement/Gamma/GammaGamma2ffAmplitude.h b/MatrixElement/Gamma/GammaGamma2ffAmplitude.h
new file mode 100644
--- /dev/null
+++ b/MatrixElement/Gamma/GammaGamma2ffAmplitude.h
@@ -0,0 +1,187 @@
+// -*- C++ -*-
+#ifndef Herwig_GammaGamma2ffAmplitude_H
+#define Herwig_GammaGamma2ffAmplitude_H
+//
+// This is the declaration of the GammaGamma2ffAmplitude class.
+//
+
+#include "GammaGammaAmplitude.h"
+#include "ThePEG/Helicity/Vertex/AbstractFFVVertex.h"
+
+namespace Herwig {
+
+using namespace ThePEG;
+
+/**
+ * The amplitude for \f$\gamma\gamma\to f\bar{f}\f$
+ *
+ * @see \ref GammaGamma2ffAmplitudeInterfaces "The interfaces"
+ * defined for GammaGamma2ffAmplitude.
+ */
+class GammaGamma2ffAmplitude: public GammaGammaAmplitude {
+
+public:
+
+  /**
+   * The default constructor.
+   */
+  GammaGamma2ffAmplitude() : process_(0) {}
+  
+public:
+
+  /** @name Virtual functions */
+  //@{
+  /**
+   * Return the order in \f$\alpha_S\f$ in which this matrix
+   * element is given.
+   */
+  virtual unsigned int orderInAlphaS() const {
+    return 0;
+  }
+
+  /**
+   * Return the order in \f$\alpha_{EW}\f$ in which this matrix
+   * element is given.
+   */
+  virtual unsigned int orderInAlphaEW() const {
+    return 2;
+  }
+
+  /**
+   * The number of internal degrees of freedom used in the matrix
+   * element.
+   */
+  virtual int nDim(unsigned int iopt) const {
+    return iopt+2;
+  }
+
+  /**
+   *  The Feynman diagrams (iopt=0 gamma gamma, iopt=1, e+e-)
+   */
+  virtual vector<DiagPtr> getDiagrams(unsigned int iopt) const;
+
+  /**
+   *  The matrix element
+   */
+  virtual double me2(const vector<VectorWaveFunction> & v1,
+		     const vector<VectorWaveFunction> & v2,
+		     const Energy2 & t1, const Energy2 & t2,
+		     const Energy2 & scale, 
+		     const vector<Lorentz5Momentum> & momenta,
+		     const cPDVector & partons,
+		     DVector & dweights) const;
+  
+  /**
+   * Matrix element for spin correlations
+   */
+  virtual ProductionMatrixElement me(const vector<VectorWaveFunction> & v1,
+				     const vector<VectorWaveFunction> & v2,
+				     tParticleVector & particles) const;
+
+  /**
+   * Return a Selector with possible colour geometries for the selected
+   * diagram weighted by their relative probabilities.
+   * @param diag the diagram chosen.
+   * @return the possible colour geometries weighted by their
+   * relative probabilities.
+   */
+  virtual Selector<const ColourLines *>
+  colourGeometries(unsigned int iopt, const cPDVector & partons, tcDiagPtr diag) const;
+
+  /**
+   * Generate the mass of the \f$\gamma\gamma\f$ system
+   */
+  virtual Energy generateW(double , const tcPDVector & partons,Energy Wmin, Energy Wmax,Energy2 & jacW, Energy2 scale);
+  //@}
+
+public:
+
+  /** @name Functions used by the persistent I/O system. */
+  //@{
+  /**
+   * Function used to write out object persistently.
+   * @param os the persistent output stream written to.
+   */
+  void persistentOutput(PersistentOStream & os) const;
+
+  /**
+   * Function used to read in object persistently.
+   * @param is the persistent input stream read from.
+   * @param version the version number of the object when written.
+   */
+  void persistentInput(PersistentIStream & is, int version);
+  //@}
+
+  /**
+   * The standard Init function used to initialize the interfaces.
+   * Called exactly once for each class by the class description system
+   * before the main function starts or
+   * when this class is dynamically loaded.
+   */
+  static void Init();
+
+protected:
+
+  /** @name Clone Methods. */
+  //@{
+  /**
+   * Make a simple clone of this object.
+   * @return a pointer to the new object.
+   */
+  virtual IBPtr clone() const;
+
+  /** Make a clone of this object, possibly modifying the cloned object
+   * to make it sane.
+   * @return a pointer to the new object.
+   */
+  virtual IBPtr fullclone() const;
+  //@}
+
+protected:
+
+  /** @name Standard Interfaced functions. */
+  //@{
+  /**
+   * Initialize this object after the setup phase before saving an
+   * EventGenerator to disk.
+   * @throws InitException if object could not be initialized properly.
+   */
+  virtual void doinit();
+  //@}
+
+protected:
+
+  /**
+   *  Calculation of the helicity amplitudes for the process
+   */
+  ProductionMatrixElement helicityAmplitude(const vector<VectorWaveFunction> & v1,
+					    const vector<VectorWaveFunction> & v2,
+					    const vector<SpinorBarWaveFunction> & f,
+					    const vector<SpinorWaveFunction>    & fbar,
+					    double & output, DVector & dweights) const;
+
+private:
+
+  /**
+   * The assignment operator is private and must never be called.
+   * In fact, it should not even be implemented.
+   */
+  GammaGamma2ffAmplitude & operator=(const GammaGamma2ffAmplitude &) = delete;
+
+private:
+  
+  /**
+   *  Which processes to include
+   */
+  int process_;
+
+  /**
+   *  Pointer to the photon vertex
+   */
+  AbstractFFVVertexPtr vertex_;
+
+};
+
+}
+
+#endif /* Herwig_GammaGamma2ffAmplitude_H */
diff --git a/MatrixElement/Gamma/GammaGammaAmplitude.cc b/MatrixElement/Gamma/GammaGammaAmplitude.cc
new file mode 100644
--- /dev/null
+++ b/MatrixElement/Gamma/GammaGammaAmplitude.cc
@@ -0,0 +1,95 @@
+// -*- C++ -*-
+//
+// This is the implementation of the non-inlined, non-templated member
+// functions of the GammaGammaAmplitude class.
+//
+
+#include "GammaGammaAmplitude.h"
+#include "ThePEG/Interface/ClassDocumentation.h"
+#include "ThePEG/EventRecord/Particle.h"
+#include "ThePEG/Repository/UseRandom.h"
+#include "ThePEG/Repository/EventGenerator.h"
+#include "ThePEG/Utilities/DescribeClass.h"
+#include "ThePEG/Utilities/SimplePhaseSpace.h"
+
+using namespace Herwig;
+
+// The following static variable is needed for the type
+// description system in ThePEG.
+DescribeAbstractNoPIOClass<GammaGammaAmplitude,Interfaced>
+describeThePEGGammaGammaAmplitude("ThePEG::GammaGammaAmplitude", "HwMEGammaGamma.so");
+
+void GammaGammaAmplitude::Init() {
+
+  static ClassDocumentation<GammaGammaAmplitude> documentation
+    ("The GammaGammaAmplitude class provides a base class for"
+     " the implementation of gamma gamma -> X processes");
+
+}
+
+Selector<const ColourLines *>
+GammaGammaAmplitude::colourGeometries(unsigned int, const cPDVector &, tcDiagPtr ) const {
+  static ColourLines c("");
+  Selector<const ColourLines *> sel;
+  sel.insert(1.0, &c);
+  return sel;
+}
+
+double GammaGammaAmplitude::generateKinematics(const double * r,
+					       const Energy2 & scale, 
+					       vector<Lorentz5Momentum> & momenta,
+					       const tcPDVector & partons) {
+  double jac = 0.25/pow(Constants::twopi,5);
+  vector<Energy> masses;
+  for(unsigned int ix=0;ix<partons.size();++ix) {
+    momenta[ix].setMass(partons[ix]->mass());
+  }
+  Energy q = ZERO;
+  try {
+    q = SimplePhaseSpace::
+      getMagnitude(scale, momenta[0].mass(), momenta[1].mass());
+  }
+  catch ( ImpossibleKinematics & e) {
+    return -1.;
+  }
+  double cth = -1.+r[0]*2.;
+  jac *= 2.*q/sqrt(scale);
+  Energy pt = q*sqrt(1.0-sqr(cth));
+  double phi = Constants::twopi*r[1];
+  momenta[0].setVect(Momentum3( pt*sin(phi),  pt*cos(phi),  q*cth));
+  momenta[1].setVect(Momentum3(-pt*sin(phi), -pt*cos(phi), -q*cth));
+  momenta[0].rescaleEnergy();
+  momenta[1].rescaleEnergy();
+  return jac;
+}
+
+ProductionMatrixElement GammaGammaAmplitude::bookME(vector<unsigned int> &ihMax,
+						    unsigned int ih1, unsigned ih2,
+						    const vector<PDT::Spin> & spin) const {
+  PDT::Spin in[2];
+  vector<PDT::Spin> spins; spins.reserve(spin.size()+2);
+  unsigned int ih[2]={ih1,ih2};
+  for(unsigned int ix=0;ix<2;++ix) {
+    if(ih[ix]==2) {
+      in[ix]=PDT::Spin1;
+      ihMax[2*ix  ] = 1;
+      ihMax[2*ix+1] = 2;
+    }
+    else if(ih[ix]==4) {
+      in[ix]=PDT::Spin1Half;
+      spins.push_back(PDT::Spin1Half);
+      ihMax[2*ix  ] = 2;
+      ihMax[2*ix+1] = 2;
+    }
+    else if(ih[ix]==1) {
+      in[ix]=PDT::Spin0;
+      spins.push_back(PDT::Spin0);
+      ihMax[2*ix  ] = 1;
+      ihMax[2*ix+1] = 1;
+    }
+    else
+      assert(false);
+  }
+  for(const PDT::Spin & s : spin) spins.push_back(s);
+  return ProductionMatrixElement(in[0],in[1],spins);
+}
diff --git a/MatrixElement/Gamma/GammaGammaAmplitude.fh b/MatrixElement/Gamma/GammaGammaAmplitude.fh
new file mode 100644
--- /dev/null
+++ b/MatrixElement/Gamma/GammaGammaAmplitude.fh
@@ -0,0 +1,18 @@
+// -*- C++ -*-
+//
+// This is the forward declaration of the GammaGammaAmplitude class.
+//
+#ifndef Herwig_GammaGammaAmplitude_FH
+#define Herwig_GammaGammaAmplitude_FH
+
+#include "ThePEG/Config/ThePEG.h"
+
+namespace Herwig {
+
+class GammaGammaAmplitude;
+
+ThePEG_DECLARE_POINTERS(Herwig::GammaGammaAmplitude,GammaGammaAmpPtr);
+
+}
+
+#endif
diff --git a/MatrixElement/Gamma/GammaGammaAmplitude.h b/MatrixElement/Gamma/GammaGammaAmplitude.h
new file mode 100644
--- /dev/null
+++ b/MatrixElement/Gamma/GammaGammaAmplitude.h
@@ -0,0 +1,147 @@
+// -*- C++ -*-
+#ifndef Herwig_GammaGammaAmplitude_H
+#define Herwig_GammaGammaAmplitude_H
+//
+// This is the declaration of the GammaGammaAmplitude class.
+//
+
+#include "ThePEG/Interface/Interfaced.h"
+#include "ThePEG/MatrixElement/Tree2toNDiagram.h"
+#include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h"
+#include "GammaGammaAmplitude.fh"
+#include "Herwig/MatrixElement/ProductionMatrixElement.h"
+
+namespace Herwig {
+  
+using namespace ThePEG;
+using Helicity::VectorWaveFunction;
+  
+/**
+ * The GammaGammaAmplitude class provides a base class for the implementation
+ * of amplitudes for $\gamma\gamma\to X$
+ *
+ * @see \ref GammaGammaAmplitudeInterfaces "The interfaces"
+ * defined for GammaGammaAmplitude.
+ */
+class GammaGammaAmplitude: public Interfaced {
+
+public:
+
+  /**
+   * The default constructor.
+   */
+  GammaGammaAmplitude()
+  {}
+  
+public:
+
+  /** @name Virtual functions */
+  //@{
+  /**
+   * Return the order in \f$\alpha_S\f$ in which this matrix
+   * element is given.
+   */
+  virtual unsigned int orderInAlphaS() const = 0;
+
+  /**
+   * Return the order in \f$\alpha_{EW}\f$ in which this matrix
+   * element is given.
+   */
+  virtual unsigned int orderInAlphaEW() const = 0;
+
+  /**
+   * The number of internal degrees of freedom used in the matrix
+   * element.
+   */
+  virtual int nDim(unsigned int iopt) const = 0;
+
+  /**
+   *  The Feynman diagrams (iopt=0 gamma gamma, iopt=1, e+e-)
+   */
+  virtual vector<DiagPtr> getDiagrams(unsigned int iopt) const = 0;
+
+  /**
+   *  The matrix element
+   */
+  virtual double me2(const vector<VectorWaveFunction> & v1,
+		     const vector<VectorWaveFunction> & v2,
+		     const Energy2 & t1, const Energy2 & t2,
+		     const Energy2 & scale, 
+		     const vector<Lorentz5Momentum> & momenta,
+		     const cPDVector & partons,
+		     DVector & dweights) const = 0;
+  
+  /**
+   *  The matrix element for spin correlations
+   */
+  virtual ProductionMatrixElement me(const vector<VectorWaveFunction> & v1,
+				     const vector<VectorWaveFunction> & v2,
+				     tParticleVector & particles) const = 0;
+
+  /**
+   * Return a Selector with possible colour geometries for the selected
+   * diagram weighted by their relative probabilities.
+   * @param diag the diagram chosen.
+   * @return the possible colour geometries weighted by their
+   * relative probabilities.
+   */
+  virtual Selector<const ColourLines *>
+  colourGeometries(unsigned int iopt,  const cPDVector & partons, tcDiagPtr diag) const;
+
+  /**
+   * Generate internal degrees of freedom given 'nDim()' uniform
+   * random numbers in the interval ]0,1[. To help the phase space
+   * generator, the 'dSigHatDR()' should be a smooth function of these
+   * numbers, although this is not strictly necessary. Return
+   * false if the chosen points failed the kinematical cuts.
+   */
+  virtual double generateKinematics(const double * r,
+				    const Energy2 & scale, 
+				    vector<Lorentz5Momentum> & momenta,
+				    const tcPDVector & partons);
+
+  /**
+   * Generate the mass of the \f$\gamma\gamma\f$ system
+   * @param r The random number to use for the generation of W
+   * @param partons The outgoing partons
+   * @param The minimum value of W
+   * @param Wmax The maximum for W
+   * @param jacW The jacobian for the gneeration of W
+   * @param scale The scale to be used to make result dimensiionless
+   * @return The generated value of W
+   */
+  virtual Energy generateW(double r, const tcPDVector & partons, Energy Wmin, Energy Wmax, Energy2 & jacW,Energy2 scale) = 0;
+  //@}
+
+protected:
+
+  /**
+   *   book the matrix element and indices for the loops
+   */
+  ProductionMatrixElement bookME(vector<unsigned int> &ihMax,
+				 unsigned int ih1, unsigned ih2,
+				 const vector<PDT::Spin> &spin) const;
+
+public:
+
+  /**
+   * The standard Init function used to initialize the interfaces.
+   * Called exactly once for each class by the class description system
+   * before the main function starts or
+   * when this class is dynamically loaded.
+   */
+  static void Init();
+
+private:
+
+  /**
+   * The assignment operator is private and must never be called.
+   * In fact, it should not even be implemented.
+   */
+  GammaGammaAmplitude & operator=(const GammaGammaAmplitude &) = delete;
+
+};
+
+}
+
+#endif /* Herwig_GammaGammaAmplitude_H */
diff --git a/MatrixElement/Gamma/MEGammaGamma2PiPi.cc b/MatrixElement/Gamma/MEGammaGamma2PiPi.cc
deleted file mode 100644
--- a/MatrixElement/Gamma/MEGammaGamma2PiPi.cc
+++ /dev/null
@@ -1,174 +0,0 @@
-// -*- C++ -*-
-//
-// This is the implementation of the non-inlined, non-templated member
-// functions of the MEGammaGamma2PiPi class.
-//
-
-#include "MEGammaGamma2PiPi.h"
-#include "ThePEG/Interface/ClassDocumentation.h"
-#include "ThePEG/EventRecord/Particle.h"
-#include "ThePEG/Repository/UseRandom.h"
-#include "ThePEG/Repository/EventGenerator.h"
-#include "ThePEG/Utilities/DescribeClass.h"
-#include "ThePEG/Persistency/PersistentOStream.h"
-#include "ThePEG/Persistency/PersistentIStream.h"
-#include "ThePEG/PDT/EnumParticles.h"
-#include "ThePEG/MatrixElement/Tree2toNDiagram.h"
-#include "ThePEG/StandardModel/StandardModelBase.h"
-#include "Herwig/MatrixElement/HardVertex.h"
-
-using namespace Herwig;
-using ThePEG::Helicity::incoming;
-
-MEGammaGamma2PiPi::MEGammaGamma2PiPi() {
-  massOption(vector<unsigned int>(2,1));
-}
-
-void MEGammaGamma2PiPi::getDiagrams() const {
-  tcPDPtr gamma = getParticleData(ParticleID::gamma);
-  tcPDPtr pip = getParticleData(ParticleID::piplus);
-  tcPDPtr pim = pip->CC();
-  // first t-channel
-  add(new_ptr((Tree2toNDiagram(3),gamma,pip,gamma,1,pip, 2,pim,-1)));
-  // interchange
-  add(new_ptr((Tree2toNDiagram(3),gamma,pip,gamma,2,pip, 1,pim,-2)));
-}
-
-Energy2 MEGammaGamma2PiPi::scale() const {
-  return 2.*sHat()*tHat()*uHat()/(sqr(sHat())+sqr(tHat())+sqr(uHat()));
-}
-
-double MEGammaGamma2PiPi::me2() const {
-  VectorWaveFunction      p1w(rescaledMomenta()[0],mePartonData()[0],incoming);
-  VectorWaveFunction      p2w(rescaledMomenta()[1],mePartonData()[1],incoming);
-  vector<VectorWaveFunction> p1,p2;
-  for(unsigned int ix=0;ix<2;++ix) {
-    p1w.reset(2*ix);p1.push_back(p1w);
-    p2w.reset(2*ix);p2.push_back(p2w);
-  }
-  // calculate the matrix element
-  return helicityME(p1,p2,rescaledMomenta(),false);
-}
-
-unsigned int MEGammaGamma2PiPi::orderInAlphaS() const {
-  return 0;
-}
-
-unsigned int MEGammaGamma2PiPi::orderInAlphaEW() const {
-  return 2;
-}
-
-Selector<MEBase::DiagramIndex>
-MEGammaGamma2PiPi::diagrams(const DiagramVector & diags) const {
-  Selector<DiagramIndex> sel;
-  for ( DiagramIndex i = 0; i < diags.size(); ++i ) 
-    if ( diags[i]->id() == -1 )      sel.insert(meInfo()[0], i);
-    else if ( diags[i]->id() == -2 ) sel.insert(meInfo()[1], i);
-  return sel;
-}
-
-Selector<const ColourLines *>
-MEGammaGamma2PiPi::colourGeometries(tcDiagPtr ) const {
-  static ColourLines c1("");
-  Selector<const ColourLines *> sel;
-  sel.insert(1.0, &c1);
-  return sel;
-}
-
-IBPtr MEGammaGamma2PiPi::clone() const {
-  return new_ptr(*this);
-}
-
-IBPtr MEGammaGamma2PiPi::fullclone() const {
-  return new_ptr(*this);
-}
-
-// The following static variable is needed for the type
-// description system in ThePEG.
-DescribeNoPIOClass<MEGammaGamma2PiPi,HwMEBase>
-describeHerwigMEGammaGamma2PiPi("Herwig::MEGammaGamma2PiPi", "HwMEGammaGamma.so");
-
-void MEGammaGamma2PiPi::Init() {
-
-  static ClassDocumentation<MEGammaGamma2PiPi> documentation
-    ("The MEGammaGamma2PiPi class provides a simple matrix element for gamma gamma -> pi+pi-");
-
-}
-
-void MEGammaGamma2PiPi::constructVertex(tSubProPtr sub) {
-  // extract the particles in the hard process
-  ParticleVector hard;
-  hard.push_back(sub->incoming().first);
-  hard.push_back(sub->incoming().second);
-  hard.push_back(sub->outgoing()[0]);
-  hard.push_back(sub->outgoing()[1]);
-  // order of particles
-  unsigned int order[4]={0,1,2,3};
-  // identify the process and calculate matrix element
-  vector<VectorWaveFunction> p1,p2;
-  if(hard[order[2]]->id()<0) swap(order[2],order[3]);
-  VectorWaveFunction   (p1  ,hard[order[0]],incoming,false,true);
-  VectorWaveFunction   (p2  ,hard[order[1]],incoming,false,true);
-  p1[1]=p1[2];
-  p2[1]=p2[2];
-  vector<Lorentz5Momentum> momenta;
-  for(unsigned int ix=0;ix<4;++ix)
-    momenta.push_back(hard[order[ix]]->momentum());
-  helicityME(p1,p2,momenta,true);
-  // construct the vertex
-  HardVertexPtr hardvertex=new_ptr(HardVertex());
-  // set the matrix element for the vertex
-  hardvertex->ME(me_);
-  // set the pointers and to and from the vertex
-  for(unsigned int ix=0;ix<4;++ix) {
-    if(hard[order[ix]]->spinInfo())
-      hard[order[ix]]->spinInfo()->productionVertex(hardvertex);
-  }
-}
-
-double MEGammaGamma2PiPi::helicityME(vector<VectorWaveFunction> &p1,
-				     vector<VectorWaveFunction> &p2,
-				     const vector<Lorentz5Momentum> & momenta,
-				     bool calc) const {
-  // for(unsigned int ix=0;ix<4;++ix)
-  //   cerr << mePartonData()[ix]->PDGName() <<" " << meMomenta()[ix]/GeV << " " << meMomenta()[ix].mass()/GeV << "\n";
-  // double beta = meMomenta()[2].vect().mag()/meMomenta()[2].t();
-  // double ct   = meMomenta()[2].cosTheta();
-  // double phi  = meMomenta()[2].phi();
-  // matrix element to be stored
-  if(calc) me_.reset(ProductionMatrixElement(PDT::Spin1,PDT::Spin1,
-  					     PDT::Spin0,PDT::Spin0));
-  // calculate the matrix element
-  double output(0.),sumdiag[2]={0.,0.};
-  Complex diag[2];
-  Energy2 d1 = momenta[0]*momenta[2], d2 = momenta[1]*momenta[2];
-  for(unsigned int ihel1=0;ihel1<2;++ihel1) {
-    complex<Energy> a1 = momenta[2]*p1[ihel1].wave();
-    complex<Energy> a2 = momenta[3]*p1[ihel1].wave();
-    for(unsigned int ihel2=0;ihel2<2;++ihel2) {
-      complex<Energy> b1 = momenta[2]*p2[ihel2].wave();
-      complex<Energy> b2 = momenta[3]*p2[ihel2].wave();
-      // t-channel diagram
-      diag[0] = a1*b2/d1;
-      // u-channel diagram
-      diag[1] = a2*b1/d2;
-      sumdiag[0] += norm(diag[0]);
-      sumdiag[1] += norm(diag[1]);
-      Complex amp = p1[ihel1].wave()*p2[ihel2].wave()-diag[0]-diag[1];
-      output += norm(amp);
-      // store the me if needed
-      if(calc) me_(2*ihel1,2*ihel2,0,0) = amp;
-    }
-  }
-  // diagrams
-  DVector save;
-  save.push_back(sumdiag[0]);
-  save.push_back(sumdiag[1]);
-  meInfo(save);
-  // code to test vs the analytic result
-  // Energy2 m2 = sqr(momenta[2].mass());
-  // double test = 2. + ((d1 + d2)*m2*(-2*d1*d2 + (d1 + d2)*m2))/(sqr(d1)*sqr(d2));
-  // cerr << "testing ME " << (output-test)/(output+test) << " " << output << " " << test << " " << output/test << "\n"; 
-  // coupling factors
-  return output*sqr(SM().alphaEM()*4.*Constants::pi);
-}
diff --git a/MatrixElement/Gamma/MEGammaGamma2PiPi.h b/MatrixElement/Gamma/MEGammaGamma2PiPi.h
deleted file mode 100644
--- a/MatrixElement/Gamma/MEGammaGamma2PiPi.h
+++ /dev/null
@@ -1,152 +0,0 @@
-// -*- C++ -*-
-#ifndef Herwig_MEGammaGamma2PiPi_H
-#define Herwig_MEGammaGamma2PiPi_H
-//
-// This is the declaration of the MEGammaGamma2PiPi class.
-//
-
-#include "Herwig/MatrixElement/HwMEBase.h"
-#include "Herwig/MatrixElement/ProductionMatrixElement.h"
-#include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h"
-
-namespace Herwig {
-
-using namespace ThePEG;
-using ThePEG::Helicity::VectorWaveFunction;
-
-/**
- * The MEGammaGamma2PiPi class provides a smiple matrix element for \f$\gamma\gamma\to \pi^+\pi^-$ using scalar QED
- *
- * @see \ref MEGammaGamma2PiPiInterfaces "The interfaces"
- * defined for MEGammaGamma2PiPi.
- */
-class MEGammaGamma2PiPi: public HwMEBase {
-
-public:
-
-  /**
-   * The default constructor.
-   */
-  MEGammaGamma2PiPi();
-
-public:
-
-  /** @name Virtual functions required by the MEBase class. */
-  //@{
-  /**
-   * Return the order in \f$\alpha_S\f$ in which this matrix
-   * element is given.
-   */
-  virtual unsigned int orderInAlphaS() const;
-
-  /**
-   * Return the order in \f$\alpha_{EW}\f$ in which this matrix
-   * element is given.
-   */
-  virtual unsigned int orderInAlphaEW() const;
-
-  /**
-   * The matrix element for the kinematical configuration
-   * previously provided by the last call to setKinematics(), suitably
-   * scaled by sHat() to give a dimension-less number.
-   * @return the matrix element scaled with sHat() to give a
-   * dimensionless number.
-   */
-  virtual double me2() const;
-
-  /**
-   * Return the scale associated with the last set phase space point.
-   */
-  virtual Energy2 scale() const;
-
-  /**
-   * Add all possible diagrams with the add() function.
-   */
-  virtual void getDiagrams() const;
-
-  /**
-   * Get diagram selector. With the information previously supplied with the
-   * setKinematics method, a derived class may optionally
-   * override this method to weight the given diagrams with their
-   * (although certainly not physical) relative probabilities.
-   * @param dv the diagrams to be weighted.
-   * @return a Selector relating the given diagrams to their weights.
-   */
-  virtual Selector<DiagramIndex> diagrams(const DiagramVector & dv) const;
-
-  /**
-   * Return a Selector with possible colour geometries for the selected
-   * diagram weighted by their relative probabilities.
-   * @param diag the diagram chosen.
-   * @return the possible colour geometries weighted by their
-   * relative probabilities.
-   */
-  virtual Selector<const ColourLines *>
-  colourGeometries(tcDiagPtr diag) const;
-  //@}
-
-  /**
-   *  Construct the vertex of spin correlations.
-   */
-  virtual void constructVertex(tSubProPtr);
-
-public:
-
-  /**
-   * The standard Init function used to initialize the interfaces.
-   * Called exactly once for each class by the class description system
-   * before the main function starts or
-   * when this class is dynamically loaded.
-   */
-  static void Init();
-
-protected:
-
-  /**
-   * Matrix element for \f$\gamma\gamma\to q\bar{q}\f$
-   * @param p1   The wavefunctions for the first  incoming photon
-   * @param p2   The wavefunctions for the second incoming photon
-   * @param momenta The momenta
-   * @param calc Whether or not to calculate the matrix element
-   */
-  double helicityME(vector<VectorWaveFunction> &p1,vector<VectorWaveFunction> &p2,
-		    const vector<Lorentz5Momentum> & momenta,
-		    bool calc) const;
-
-protected:
-
-  /** @name Clone Methods. */
-  //@{
-  /**
-   * Make a simple clone of this object.
-   * @return a pointer to the new object.
-   */
-  virtual IBPtr clone() const;
-
-  /** Make a clone of this object, possibly modifying the cloned object
-   * to make it sane.
-   * @return a pointer to the new object.
-   */
-  virtual IBPtr fullclone() const;
-  //@}
-
-private:
-
-  /**
-   * The assignment operator is private and must never be called.
-   * In fact, it should not even be implemented.
-   */
-  MEGammaGamma2PiPi & operator=(const MEGammaGamma2PiPi &) = delete;
-
-private:
-
-  /**
-   *  Matrix element
-   */
-  mutable ProductionMatrixElement me_;
-
-};
-
-}
-
-#endif /* Herwig_MEGammaGamma2PiPi_H */
diff --git a/MatrixElement/Gamma/MEGammaGamma2X.cc b/MatrixElement/Gamma/MEGammaGamma2X.cc
new file mode 100644
--- /dev/null
+++ b/MatrixElement/Gamma/MEGammaGamma2X.cc
@@ -0,0 +1,174 @@
+// -*- C++ -*-
+//
+// This is the implementation of the non-inlined, non-templated member
+// functions of the MEGammaGamma2X class.
+//
+
+#include "MEGammaGamma2X.h"
+#include "ThePEG/Interface/ClassDocumentation.h"
+#include "ThePEG/EventRecord/Particle.h"
+#include "ThePEG/Repository/UseRandom.h"
+#include "ThePEG/Repository/EventGenerator.h"
+#include "ThePEG/Utilities/DescribeClass.h"
+#include "ThePEG/Persistency/PersistentOStream.h"
+#include "ThePEG/Persistency/PersistentIStream.h"
+#include "ThePEG/PDT/EnumParticles.h"
+#include "ThePEG/MatrixElement/Tree2toNDiagram.h"
+#include "ThePEG/Interface/Reference.h"
+#include "ThePEG/Cuts/Cuts.h"
+#include "Herwig/MatrixElement/HardVertex.h"
+
+using namespace Herwig;
+
+void MEGammaGamma2X::getDiagrams() const {
+  vector<DiagPtr> diags = amp_->getDiagrams(0);
+  for(DiagPtr diag : diags) add(diag);
+}
+
+void MEGammaGamma2X::setKinematics() {
+  HwMEBase::setKinematics(); // Always call the base class method first.
+}
+
+IBPtr MEGammaGamma2X::clone() const {
+  return new_ptr(*this);
+}
+
+IBPtr MEGammaGamma2X::fullclone() const {
+  return new_ptr(*this);
+}
+
+void MEGammaGamma2X::persistentOutput(PersistentOStream & os) const {
+  os << amp_;
+}
+
+void MEGammaGamma2X::persistentInput(PersistentIStream & is, int) {
+  is >> amp_;
+}
+
+// The following static variable is needed for the type
+// description system in ThePEG.
+DescribeClass<MEGammaGamma2X,HwMEBase>
+describeHerwigMEGammaGamma2X("Herwig::MEGammaGamma2X", "HwMEGammaGamma.so");
+
+void MEGammaGamma2X::Init() {
+
+  static ClassDocumentation<MEGammaGamma2X> documentation
+    ("The MEGammaGamma2X class implements the matrix element for gamma gamma ->X");
+  
+  static Reference<MEGammaGamma2X,GammaGammaAmplitude> interfaceAmplitude
+    ("Amplitude",
+     "The gamma gamma -> X amplitude",
+     &MEGammaGamma2X::amp_, false, false, true, false, false);
+
+}
+
+Selector<const ColourLines *>
+MEGammaGamma2X::colourGeometries(tcDiagPtr diag) const {
+  return amp_->colourGeometries(0,mePartonData(),diag);
+}
+
+bool MEGammaGamma2X::generateKinematics(const double * r) {
+  vector<Lorentz5Momentum> pout(meMomenta().size()-2);
+  tcPDVector tout(mePartonData().begin()+2,mePartonData().end());
+  double jac = amp_->generateKinematics(r,sHat(),pout,tout);
+  if(jac<0.) return false;
+  jacobian(jac);
+  for(unsigned int ix=0;ix<pout.size();++ix)
+    meMomenta()[ix+2] = pout[ix];
+  vector<LorentzMomentum> p2out(meMomenta().size()-2);
+  for(unsigned int ix=0;ix<pout.size();++ix)
+    p2out[ix] = pout[ix];
+  return lastCuts().passCuts(tout, p2out, mePartonData()[0], mePartonData()[1]);
+}
+
+Energy2 MEGammaGamma2X::scale() const {
+  return sHat();
+}
+
+CrossSection MEGammaGamma2X::dSigHatDR() const {
+  return 0.5*sqr(hbarc)*me2()*jacobian()*pow(Constants::twopi,4)/sHat();
+}
+
+double MEGammaGamma2X::me2() const {
+  using ThePEG::Helicity::incoming;
+  VectorWaveFunction      p1w(meMomenta()[0],mePartonData()[0],incoming);
+  VectorWaveFunction      p2w(meMomenta()[1],mePartonData()[1],incoming);
+  vector<VectorWaveFunction> p1,p2;
+  for(unsigned int ix=0;ix<2;++ix) {
+    p1w.reset(2*ix);p1.push_back(p1w);
+    p2w.reset(2*ix);p2.push_back(p2w);
+    //p1w.reset(10);p1.push_back(p1w);
+    //p2w.reset(10);p2.push_back(p2w);
+  }
+  DVector save;
+  double output =  amp_->me2(p1,p2,meMomenta()[0].m2(),meMomenta()[1].m2(),sHat(),
+			     vector<Lorentz5Momentum>(meMomenta().begin()+2,meMomenta().end()),
+			     cPDVector(mePartonData().begin()+2,mePartonData().end()),save);
+  meInfo(save);
+  return output;
+}
+
+Selector<MEBase::DiagramIndex>
+MEGammaGamma2X::diagrams(const DiagramVector & diags) const {
+  Selector<DiagramIndex> sel;
+  for ( DiagramIndex i = 0; i < diags.size(); ++i ) {
+    unsigned int id = abs(diags[i]->id())-1;
+    if(id<meInfo().size())
+      sel.insert(meInfo()[id], i);
+    else if ( meInfo().empty() ) sel.insert(1., i);
+    else
+      assert(false);
+  }
+  return sel;
+}
+
+void MEGammaGamma2X::constructVertex(tSubProPtr sub) {
+  using namespace ThePEG::Helicity;
+  // extract the particles in the hard process
+  tParticleVector hard;
+  hard.reserve(sub->outgoing().size()+2);
+  hard.push_back(sub->incoming().first);
+  hard.push_back(sub->incoming().second);
+  for(unsigned int ix=0;ix<sub->outgoing().size();++ix)
+    hard.push_back(sub->outgoing()[ix]);
+  // calculate the photon currents (removing null 0 state)
+  vector<VectorWaveFunction> p1,p2;
+  VectorWaveFunction   (p1,hard[0],incoming,false,true );
+  p1[1]=p1[2];p1.resize(2);
+  VectorWaveFunction   (p2,hard[1],incoming,false,true );
+  p2[1]=p2[2];p2.resize(2);
+  tParticleVector pTemp(hard.begin()+2,hard.end());
+  ProductionMatrixElement me = amp_->me(p1,p2,pTemp);
+  // // for(auto part : hard ) cerr << *part << "\n";
+  // // for(unsigned int ih1=0;ih1<2;++ih1)
+  // //   for(unsigned int ih2=0;ih2<2;++ih2)
+  // // 	  for(unsigned int ih5=0;ih5<hard.back()->dataPtr()->iSpin();++ih5)
+  // // 	    cerr << ih1 << " " << ih2 << " " << ih5 << " " << me(ih1,ih2,ih5) << "\n";
+  // construct the vertex
+  HardVertexPtr hardvertex=new_ptr(HardVertex());
+  // set the matrix element for the vertex
+  hardvertex->ME(me);
+  // set the pointers and to and from the vertex
+  for(unsigned int ix=0;ix<hard.size();++ix) {
+    hard[ix]->spinInfo()->productionVertex(hardvertex);
+  }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/MatrixElement/Gamma/MEGammaGamma2X.h b/MatrixElement/Gamma/MEGammaGamma2X.h
new file mode 100644
--- /dev/null
+++ b/MatrixElement/Gamma/MEGammaGamma2X.h
@@ -0,0 +1,192 @@
+// -*- C++ -*-
+#ifndef Herwig_MEGammaGamma2X_H
+#define Herwig_MEGammaGamma2X_H
+//
+// This is the declaration of the MEGammaGamma2X class.
+//
+
+#include "Herwig/MatrixElement/HwMEBase.h"
+#include "GammaGammaAmplitude.h"
+
+namespace Herwig {
+
+using namespace ThePEG;
+
+/**
+ * The MEGammaGamma2X class implements the matrix element for $\gamma\gamma\to X$ processes using
+ * the GammaGammaAmplitude
+ *
+ * @see \ref MEGammaGamma2XInterfaces "The interfaces"
+ * defined for MEGammaGamma2X.
+ */
+class MEGammaGamma2X: public HwMEBase {
+
+public:
+  
+  /**
+   * The default constructor.
+   */
+  MEGammaGamma2X() {}
+
+public:
+
+  /** @name Virtual functions required by the MEBase class. */
+  //@{
+  /**
+   * Return the order in \f$\alpha_S\f$ in which this matrix
+   * element is given.
+   */
+  virtual unsigned int orderInAlphaS() const {
+    return amp_->orderInAlphaS();    
+  }
+
+  /**
+   * Return the order in \f$\alpha_{EW}\f$ in which this matrix
+   * element is given.
+   */
+  virtual unsigned int orderInAlphaEW() const {
+    return amp_->orderInAlphaS();
+  }
+
+  /**
+   * The matrix element for the kinematical configuration
+   * previously provided by the last call to setKinematics(), suitably
+   * scaled by sHat() to give a dimension-less number.
+   * @return the matrix element scaled with sHat() to give a
+   * dimensionless number.
+   */
+  virtual double me2() const;
+
+  /**
+   * Return the scale associated with the last set phase space point.
+   */
+  virtual Energy2 scale() const;
+
+  /**
+   * Set the typed and momenta of the incoming and outgoing partons to
+   * be used in subsequent calls to me() and colourGeometries()
+   * according to the associated XComb object. If the function is
+   * overridden in a sub class the new function must call the base
+   * class one first.
+   */
+  virtual void setKinematics();
+
+  /**
+   * The number of internal degrees of freedom used in the matrix
+   * element.
+   */
+  virtual int nDim() const {
+    return amp_->nDim(0);
+  }
+
+  /**
+   * Generate internal degrees of freedom given nDim() uniform
+   * random numbers in the interval \f$ ]0,1[ \f$. To help the phase space
+   * generator, the dSigHatDR should be a smooth function of these
+   * numbers, although this is not strictly necessary.
+   * @param r a pointer to the first of nDim() consecutive random numbers.
+   * @return true if the generation succeeded, otherwise false.
+   */
+  virtual bool generateKinematics(const double * r);
+
+  /**
+   * Return the matrix element squared differential in the variables
+   * given by the last call to generateKinematics().
+   */
+  virtual CrossSection dSigHatDR() const;
+
+  /**
+   * Add all possible diagrams with the add() function.
+   */
+  virtual void getDiagrams() const;
+
+  /**
+   * Get diagram selector. With the information previously supplied with the
+   * setKinematics method, a derived class may optionally
+   * override this method to weight the given diagrams with their
+   * (although certainly not physical) relative probabilities.
+   * @param dv the diagrams to be weighted.
+   * @return a Selector relating the given diagrams to their weights.
+   */
+  virtual Selector<DiagramIndex> diagrams(const DiagramVector & dv) const;
+
+  /**
+   * Return a Selector with possible colour geometries for the selected
+   * diagram weighted by their relative probabilities.
+   * @param diag the diagram chosen.
+   * @return the possible colour geometries weighted by their
+   * relative probabilities.
+   */
+  virtual Selector<const ColourLines *>
+  colourGeometries(tcDiagPtr diag) const;
+
+  /**
+   *  Construct the vertex of spin correlations.
+   */
+  virtual void constructVertex(tSubProPtr);
+  //@}
+
+
+public:
+
+  /** @name Functions used by the persistent I/O system. */
+  //@{
+  /**
+   * Function used to write out object persistently.
+   * @param os the persistent output stream written to.
+   */
+  void persistentOutput(PersistentOStream & os) const;
+
+  /**
+   * Function used to read in object persistently.
+   * @param is the persistent input stream read from.
+   * @param version the version number of the object when written.
+   */
+  void persistentInput(PersistentIStream & is, int version);
+  //@}
+
+  /**
+   * The standard Init function used to initialize the interfaces.
+   * Called exactly once for each class by the class description system
+   * before the main function starts or
+   * when this class is dynamically loaded.
+   */
+  static void Init();
+
+protected:
+
+  /** @name Clone Methods. */
+  //@{
+  /**
+   * Make a simple clone of this object.
+   * @return a pointer to the new object.
+   */
+  virtual IBPtr clone() const;
+
+  /** Make a clone of this object, possibly modifying the cloned object
+   * to make it sane.
+   * @return a pointer to the new object.
+   */
+  virtual IBPtr fullclone() const;
+  //@}
+
+private:
+
+  /**
+   * The assignment operator is private and must never be called.
+   * In fact, it should not even be implemented.
+   */
+  MEGammaGamma2X & operator=(const MEGammaGamma2X &) = delete;
+
+private:
+
+  /**
+   *  Pointer to the amplitude for the \f$\gamma\gamma$ process
+   */
+  GammaGammaAmpPtr amp_;
+  
+};
+
+}
+
+#endif /* Herwig_MEGammaGamma2X_H */
diff --git a/MatrixElement/Gamma/MEGammaGamma2ff.cc b/MatrixElement/Gamma/MEGammaGamma2ff.cc
deleted file mode 100644
--- a/MatrixElement/Gamma/MEGammaGamma2ff.cc
+++ /dev/null
@@ -1,275 +0,0 @@
-// -*- C++ -*-
-//
-// This is the implementation of the non-inlined, non-templated member
-// functions of the MEGammaGamma2ff class.
-//
-
-#include "MEGammaGamma2ff.h"
-#include "ThePEG/Utilities/DescribeClass.h"
-#include "ThePEG/Interface/ClassDocumentation.h"
-#include "ThePEG/Persistency/PersistentOStream.h"
-#include "ThePEG/Persistency/PersistentIStream.h"
-#include "ThePEG/PDT/EnumParticles.h"
-#include "ThePEG/MatrixElement/Tree2toNDiagram.h"
-#include "ThePEG/Interface/Switch.h"
-#include "Herwig/Models/StandardModel/StandardModel.h"
-#include "ThePEG/Handlers/StandardXComb.h"
-#include "Herwig/MatrixElement/HardVertex.h"
-
-using namespace Herwig;
-
-MEGammaGamma2ff::MEGammaGamma2ff() : process_(0) {
-  massOption(vector<unsigned int>(2,1));
-}
-
-void MEGammaGamma2ff::doinit() {
-  HwMEBase::doinit();
-  // cast the SM pointer to the Herwig SM pointer
-  tcHwSMPtr hwsm=ThePEG::dynamic_ptr_cast<tcHwSMPtr>(standardModel());
-  // do the initialisation
-  if(!hwsm)
-    throw InitException() << "Must be the Herwig StandardModel class in "
-			  << "MEGammaGamma2ff::doinit" << Exception::abortnow;
-  vertex_ = hwsm->vertexFFP();
-}
-
-void MEGammaGamma2ff::getDiagrams() const {
-  tcPDPtr gamma = getParticleData(ParticleID::gamma);
-  for(int ix=1;ix<17;++ix) {
-    // increment counter to switch between quarks and leptons
-    if(ix==7) ix+=4;
-    if(ix>11&&ix%2==0) ++ix;
-    // is it a valid quark process
-    bool quark = ix<=6 && (process_==0 || process_==1 || process_-10==ix);
-    // is it a valid lepton process
-    bool lepton= ix>=11 && ix<=16 && 
-      (process_==0 || process_==2 || ( (ix-9)/2 ==process_-4) );
-    // only add diagram if allowed
-    if(!quark && !lepton) continue;
-    tcPDPtr lm = getParticleData(ix);
-    tcPDPtr lp = lm->CC();
-    // first t-channel
-    add(new_ptr((Tree2toNDiagram(3),gamma,lp,gamma,1,lm, 2,lp,-1)));
-    // interchange
-    add(new_ptr((Tree2toNDiagram(3),gamma,lp,gamma,2,lm, 1,lp,-2)));
-  }
-}
-
-Energy2 MEGammaGamma2ff::scale() const {
-  return 2.*sHat()*tHat()*uHat()/(sqr(sHat())+sqr(tHat())+sqr(uHat()));
-}
-
-double MEGammaGamma2ff::me2() const {
-  VectorWaveFunction      p1w(rescaledMomenta()[0],mePartonData()[0],incoming);
-  VectorWaveFunction      p2w(rescaledMomenta()[1],mePartonData()[1],incoming);
-  SpinorBarWaveFunction    fw(rescaledMomenta()[2],mePartonData()[2],outgoing);
-  SpinorWaveFunction    fbarw(rescaledMomenta()[3],mePartonData()[3],outgoing);
-  vector<VectorWaveFunction> p1,p2;
-  vector<SpinorBarWaveFunction> f;
-  vector<SpinorWaveFunction> fbar;
-  for(unsigned int ix=0;ix<2;++ix) {
-    p1w.reset(2*ix);p1.push_back(p1w);
-    p2w.reset(2*ix);p2.push_back(p2w);
-    fw.reset(ix);f.push_back(fw);
-    fbarw.reset(ix);fbar.push_back(fbarw);
-  }
-  // calculate the matrix element
-  return helicityME(p1,p2,f,fbar,false);
-}
-
-unsigned int MEGammaGamma2ff::orderInAlphaS() const {
-  return 0;
-}
-
-unsigned int MEGammaGamma2ff::orderInAlphaEW() const {
-  return 2;
-}
-
-double MEGammaGamma2ff::helicityME(vector<VectorWaveFunction> &p1,
-				   vector<VectorWaveFunction> &p2,
-				   vector<SpinorBarWaveFunction> & f,
-				   vector<SpinorWaveFunction> & fbar, bool calc) const {
-  // scale (external photons so scale in couplings is 0)
-  Energy2 mt(0.*GeV2);
-  // matrix element to be stored
-  if(calc) me_.reset(ProductionMatrixElement(PDT::Spin1,PDT::Spin1,
-					     PDT::Spin1Half,PDT::Spin1Half));
-  // calculate the matrix element
-  double output(0.),sumdiag[2]={0.,0.};
-  Complex diag[2];
-  SpinorWaveFunction inters;
-  for(unsigned int ihel1=0;ihel1<2;++ihel1) { 
-    for(unsigned int ihel2=0;ihel2<2;++ihel2) {
-      for(unsigned int ohel1=0;ohel1<2;++ohel1) { 
-	for(unsigned int ohel2=0;ohel2<2;++ohel2) {
-	  //first t-channel diagram
-	  inters =vertex_->evaluate(mt,1,fbar[ohel2].particle()->CC(),
-				    fbar[ohel2],p2[ihel2]);
-	  diag[0]=vertex_->evaluate(mt,inters,f[ohel1],p1[ihel1]);
-	  //second t-channel diagram
-	  inters =vertex_->evaluate(mt,1,fbar[ohel2].particle()->CC(),
-				    fbar[ohel2],p1[ihel1]);
-	  diag[1]=vertex_->evaluate(mt,inters,f[ohel1],p2[ihel2]);
-	  sumdiag[0] += norm(diag[0]);
-	  sumdiag[1] += norm(diag[1]);
-	  diag[0] += diag[1];
-	  output += norm(diag[0]);
-	  // store the me if needed
-	  if(calc) me_(2*ihel1,2*ihel2,ohel1,ohel2) = diag[0];
-	}
-      }
-    }
-  }
-  // diagrams
-  DVector save;
-  save.push_back(sumdiag[0]);
-  save.push_back(sumdiag[1]);
-  meInfo(save);
-  // colour factors if needed
-  if(mePartonData()[2]->coloured()) output *= 3.;
-  // // code to test vs the analytic result
-  // Energy2 m2 = sqr(f[0].particle()->mass());
-  // Energy2 tm = (p1[0].momentum()+f   [0].momentum()).m2()-m2;
-  // Energy2 um = (p1[0].momentum()+fbar[0].momentum()).m2()-m2;
-  // double test = 8.*um/tm+8.*tm/um- 32*m2/tm - 32*m2/um
-  //   -32*sqr(double(m2/tm)) - 64*sqr(m2)/tm/um - 32*sqr(double(m2/um));
-  // test *= sqr(4.*Constants::pi*SM().alphaEM());
-  // if(mePartonData()[2]->coloured()) test *= 3.;
-  // cerr << "testing ME " << (output-test)/(output+test) << "\n"; 
-  // spin factors
-  return 0.25*output;
-}
-
-Selector<MEBase::DiagramIndex>
-MEGammaGamma2ff::diagrams(const DiagramVector & diags) const {
-  Selector<DiagramIndex> sel;
-  for ( DiagramIndex i = 0; i < diags.size(); ++i ) 
-    if ( diags[i]->id() == -1 )      sel.insert(meInfo()[0], i);
-    else if ( diags[i]->id() == -2 ) sel.insert(meInfo()[1], i);
-  return sel;
-}
-
-Selector<const ColourLines *>
-MEGammaGamma2ff::colourGeometries(tcDiagPtr ) const {
-  static ColourLines c1("");
-  static ColourLines c2("4 -2 -5"); 
-  Selector<const ColourLines *> sel;
-  if(mePartonData()[2]->coloured()) sel.insert(1.0, &c2);
-  else                              sel.insert(1.0, &c1);
-  return sel;
-}
-
-void MEGammaGamma2ff::persistentOutput(PersistentOStream & os) const {
-  os << process_ << vertex_;
-}
-
-void MEGammaGamma2ff::persistentInput(PersistentIStream & is, int) {
-  is >> process_ >> vertex_;
-}
-
-// The following static variable is needed for the type
-// description system in ThePEG.
-DescribeClass<MEGammaGamma2ff,HwMEBase>
-describeHerwigMEGammaGamma2ff("Herwig::MEGammaGamma2ff", "HwMEGammaGamma.so");
-
-void MEGammaGamma2ff::Init() {
-
-  static ClassDocumentation<MEGammaGamma2ff> documentation
-    ("The MEGammaGamma2ff class implements the matrix elemments for"
-     " direct fermion-antifermion production in gamma-gamma collisions.");
-
-  static Switch<MEGammaGamma2ff,int> interfaceProcess
-    ("Process",
-     "Which process to included",
-     &MEGammaGamma2ff::process_, 0, false, false);
-  static SwitchOption interfaceProcessAll
-    (interfaceProcess,
-     "All",
-     "Include all SM fermions as outgoing particles",
-     0);
-  static SwitchOption interfaceProcessQuarks
-    (interfaceProcess,
-     "Quarks",
-     "All include the quarks as outgoing particles",
-     1);
-  static SwitchOption interfaceProcessLeptons
-    (interfaceProcess,
-     "Leptons",
-     "Only include the leptons as outgoing particles",
-     2);
-  static SwitchOption interfaceProcessElectron
-    (interfaceProcess,
-     "Electron",
-     "Only include e+e- as outgoing particles",
-     5);
-  static SwitchOption interfaceProcessMuon
-    (interfaceProcess,
-     "Muon",
-     "Only include mu+mu- as outgoing particles",
-     6);
-  static SwitchOption interfaceProcessTau
-    (interfaceProcess,
-     "Tau",
-     "Only include tau+tau- as outgoing particles",
-     7);
-  static SwitchOption interfaceProcessDown
-    (interfaceProcess,
-     "Down",
-     "Only include d dbar as outgoing particles",
-     11);
-  static SwitchOption interfaceProcessUp
-    (interfaceProcess,
-     "Up",
-     "Only include u ubar as outgoing particles",
-     12);
-  static SwitchOption interfaceProcessStrange
-    (interfaceProcess,
-     "Strange",
-     "Only include s sbar as outgoing particles",
-     13);
-  static SwitchOption interfaceProcessCharm
-    (interfaceProcess,
-     "Charm",
-     "Only include c cbar as outgoing particles",
-     14);
-  static SwitchOption interfaceProcessBottom
-    (interfaceProcess,
-     "Bottom",
-     "Only include b bbar as outgoing particles",
-     15);
-  static SwitchOption interfaceProcessTop
-    (interfaceProcess,
-     "Top",
-     "Only include t tbar as outgoing particles",
-     16);
-}
-
-void MEGammaGamma2ff::constructVertex(tSubProPtr sub) {
-  // extract the particles in the hard process
-  ParticleVector hard;
-  hard.push_back(sub->incoming().first);
-  hard.push_back(sub->incoming().second);
-  hard.push_back(sub->outgoing()[0]);
-  hard.push_back(sub->outgoing()[1]);
-  // order of particles
-  unsigned int order[4]={0,1,2,3};
-  // identify the process and calculate matrix element
-  vector<VectorWaveFunction> p1,p2;
-  if(hard[order[2]]->id()<0) swap(order[2],order[3]);
-  vector<SpinorWaveFunction> fbar;
-  vector<SpinorBarWaveFunction>  f;
-  VectorWaveFunction   (p1  ,hard[order[0]],incoming,false,true);
-  VectorWaveFunction   (p2  ,hard[order[1]],incoming,false,true);
-  SpinorBarWaveFunction(f   ,hard[order[2]],outgoing,true );
-  SpinorWaveFunction   (fbar,hard[order[3]],outgoing,true );
-  p1[1]=p1[2];
-  p2[1]=p2[2];
-  helicityME(p1,p2,f,fbar,true);
-  // construct the vertex
-  HardVertexPtr hardvertex=new_ptr(HardVertex());
-  // set the matrix element for the vertex
-  hardvertex->ME(me_);
-  // set the pointers and to and from the vertex
-  for(unsigned int ix=0;ix<4;++ix)
-    hard[order[ix]]->spinInfo()->productionVertex(hardvertex);
-}
diff --git a/MatrixElement/Gamma/MEGammaGamma2ff.h b/MatrixElement/Gamma/MEGammaGamma2ff.h
deleted file mode 100644
--- a/MatrixElement/Gamma/MEGammaGamma2ff.h
+++ /dev/null
@@ -1,191 +0,0 @@
-// -*- C++ -*-
-#ifndef HERWIG_MEGammaGamma2ff_H
-#define HERWIG_MEGammaGamma2ff_H
-//
-// This is the declaration of the MEGammaGamma2ff class.
-//
-
-#include "Herwig/MatrixElement/HwMEBase.h"
-#include "Herwig/MatrixElement/ProductionMatrixElement.h"
-#include "ThePEG/Helicity/WaveFunction/SpinorWaveFunction.h"
-#include "ThePEG/Helicity/WaveFunction/SpinorBarWaveFunction.h"
-#include "ThePEG/Helicity/WaveFunction/VectorWaveFunction.h"
-#include "ThePEG/Helicity/Vertex/AbstractFFVVertex.fh"
-
-namespace Herwig {
-
-using namespace ThePEG;
-
-/**
- * The MEGammaGamma2ff class provides the matrix elements for
- * \f$\gamma\gamma\to f \bar{f}\f$.
- *
- * @see \ref MEGammaGamma2ffInterfaces "The interfaces"
- * defined for MEGammaGamma2ff.
- */
-class MEGammaGamma2ff: public HwMEBase {
-
-public:
-
-  /**
-   * The default constructor.
-   */
-  MEGammaGamma2ff();
-
-  /** @name Virtual functions required by the MEBase class. */
-  //@{
-  /**
-   * Return the order in \f$\alpha_S\f$ in which this matrix
-   * element is given.
-   */
-  virtual unsigned int orderInAlphaS() const;
-
-  /**
-   * Return the order in \f$\alpha_{EW}\f$ in which this matrix
-   * element is given.
-   */
-  virtual unsigned int orderInAlphaEW() const;
-
-  /**
-   * The matrix element for the kinematical configuration
-   * previously provided by the last call to setKinematics(), suitably
-   * scaled by sHat() to give a dimension-less number.
-   * @return the matrix element scaled with sHat() to give a
-   * dimensionless number.
-   */
-  virtual double me2() const;
-
-  /**
-   * Return the scale associated with the last set phase space point.
-   */
-  virtual Energy2 scale() const;
-
-  /**
-   * Add all possible diagrams with the add() function.
-   */
-  virtual void getDiagrams() const;
-
-  /**
-   * Get diagram selector. With the information previously supplied with the
-   * setKinematics method, a derived class may optionally
-   * override this method to weight the given diagrams with their
-   * (although certainly not physical) relative probabilities.
-   * @param dv the diagrams to be weighted.
-   * @return a Selector relating the given diagrams to their weights.
-   */
-  virtual Selector<DiagramIndex> diagrams(const DiagramVector & dv) const;
-
-  /**
-   * Return a Selector with possible colour geometries for the selected
-   * diagram weighted by their relative probabilities.
-   * @param diag the diagram chosen.
-   * @return the possible colour geometries weighted by their
-   * relative probabilities.
-   */
-  virtual Selector<const ColourLines *>
-  colourGeometries(tcDiagPtr diag) const;
-
-  /**
-   *  Construct the vertex of spin correlations.
-   */
-  virtual void constructVertex(tSubProPtr);
-  //@}
-
-public:
-
-  /** @name Functions used by the persistent I/O system. */
-  //@{
-  /**
-   * Function used to write out object persistently.
-   * @param os the persistent output stream written to.
-   */
-  void persistentOutput(PersistentOStream & os) const;
-
-  /**
-   * Function used to read in object persistently.
-   * @param is the persistent input stream read from.
-   * @param version the version number of the object when written.
-   */
-  void persistentInput(PersistentIStream & is, int version);
-  //@}
-
-  /**
-   * The standard Init function used to initialize the interfaces.
-   * Called exactly once for each class by the class description system
-   * before the main function starts or
-   * when this class is dynamically loaded.
-   */
-  static void Init();
-
-protected:
-
-  /**
-   * Matrix element for \f$\gamma\gamma\to q\bar{q}\f$
-   * @param p1   The wavefunctions for the first  incoming photon
-   * @param p2   The wavefunctions for the second incoming photon
-   * @param f    The wavefunction  for the outgoing fermion
-   * @param fbar The wavefunction  for the outgoing antifermion
-   * @param calc Whether or not to calculate the matrix element
-   */
-  double helicityME(vector<VectorWaveFunction> &p1,vector<VectorWaveFunction> &p2,
-		    vector<SpinorBarWaveFunction> & f,
-		    vector<SpinorWaveFunction> & fbar, bool calc) const;
-protected:
-
-  /** @name Clone Methods. */
-  //@{
-  /**
-   * Make a simple clone of this object.
-   * @return a pointer to the new object.
-   */
-  virtual IBPtr clone() const {return new_ptr(*this);}
-
-  /** Make a clone of this object, possibly modifying the cloned object
-   * to make it sane.
-   * @return a pointer to the new object.
-   */
-  virtual IBPtr fullclone() const {return new_ptr(*this);}
-  //@}
-
-protected:
-
-  /** @name Standard Interfaced functions. */
-  //@{
-  /**
-   * Initialize this object after the setup phase before saving an
-   * EventGenerator to disk.
-   * @throws InitException if object could not be initialized properly.
-   */
-  virtual void doinit();
-  //@}
-
-private:
-
-  /**
-   * The assignment operator is private and must never be called.
-   * In fact, it should not even be implemented.
-   */
-  MEGammaGamma2ff & operator=(const MEGammaGamma2ff &) = delete;
-
-private:
-  
-  /**
-   *  Which processes to include
-   */
-  int process_;
-
-  /**
-   *  Pointer to the photon vertex
-   */
-  AbstractFFVVertexPtr vertex_;
-
-  /**
-   *  Matrix element
-   */
-  mutable ProductionMatrixElement me_;
-
-};
-
-}
-
-#endif /* HERWIG_MEGammaGamma2ff_H */
diff --git a/MatrixElement/Gamma/MEff2ffX.cc b/MatrixElement/Gamma/MEff2ffX.cc
new file mode 100644
--- /dev/null
+++ b/MatrixElement/Gamma/MEff2ffX.cc
@@ -0,0 +1,680 @@
+// -*- C++ -*-
+//
+// This is the implementation of the non-inlined, non-templated member
+// functions of the MEff2ffX class.
+//
+
+#include "MEff2ffX.h"
+#include "ThePEG/Interface/ClassDocumentation.h"
+#include "ThePEG/Interface/Switch.h"
+#include "ThePEG/Interface/Parameter.h"
+#include "ThePEG/Interface/Reference.h"
+#include "ThePEG/EventRecord/Particle.h"
+#include "ThePEG/Repository/UseRandom.h"
+#include "ThePEG/Repository/EventGenerator.h"
+#include "ThePEG/Utilities/DescribeClass.h"
+#include "ThePEG/Persistency/PersistentOStream.h"
+#include "ThePEG/Persistency/PersistentIStream.h"
+#include "ThePEG/PDT/EnumParticles.h"
+#include "ThePEG/MatrixElement/Tree2toNDiagram.h"
+#include "ThePEG/Cuts/Cuts.h"
+#include "Herwig/MatrixElement/HardVertex.h"
+
+using namespace Herwig;
+
+void MEff2ffX::getDiagrams() const {
+  vector<DiagPtr> diags = amp_->getDiagrams(1);
+  for(DiagPtr diag : diags) add(diag);
+}
+
+Energy2 MEff2ffX::scale() const {
+  return sHat();
+}
+
+int MEff2ffX::nDim() const {
+  return 4+amp_->nDim(1);
+}
+
+void MEff2ffX::setKinematics() {
+  HwMEBase::setKinematics(); // Always call the base class method first.
+}
+
+bool MEff2ffX::generateKinematics(const double * r) {
+  // initialise the jacobian
+  jacobian(1.);
+  // roots
+  Energy rS(sqrt(sHat()));
+  Energy W(ZERO);
+  Energy m = mePartonData()[0]->mass();
+  if(amp_->nDim(1)==0) {
+    W = mePartonData()[4]->mass();
+  }
+  else {
+    Energy2 jacW(ZERO);
+    Energy Wmax = rS-2.*m;
+    W = amp_->generateW(r[4],tcPDVector(mePartonData().begin()+4,mePartonData().end()),mHatMin_,Wmax,jacW,sHat());
+    jacobian(jacW*jacobian()/sHat());
+  }
+  Energy2 m2=sqr(m), W2=sqr(W);
+  double beta = sqrt(1.-4.*m2/sHat());
+  // initialise the jacobian
+  jacobian(jacobian()*0.25*sqr(Constants::pi)/beta);
+  // outer integral is t2
+  Energy2 deltat2 = beta*sqrt((sHat()-W2)*(sHat()-sqr(W+2.*m)));
+  Energy2 t2min = -0.5*(sHat()-W2-2.*m*W-4.*m2+deltat2);
+  Energy2 t2max = sqr(m*W*(W+2.*m))/t2min/sHat();
+  Energy2 thmin = lastCuts().minTij(mePartonData()[0], mePartonData()[2]);
+  if(thmin>abs(t2max)) t2max=-thmin;
+  if(abs(t2max)<Q2_2min_) t2max= -Q2_2min_;
+  if(abs(t2min)>Q2_2max_) t2min= -Q2_2max_;
+  if(t2max<t2min) return false;
+  t2_ = t2min*pow(t2max/t2min,r[0]);
+  double y2 = sqrt(1.-4.*m2/t2_);
+  jacobian(jacobian()*log(t2max/t2min)*t2_/sHat());
+  // then t1
+  Energy2 Q  = (t2_*sHat() - m2*t2_ - sqr(m*W) -sHat()*t2_*beta*y2)/m2;
+  Energy2 a1 = 2.*(Q+t2_+2.*m2+W2);
+  Energy4 b1 = sqr(Q)-8.*m2*t2_-sqr(t2_)-8.*sqr(m*W)+2.*t2_*W2-pow<4,1>(W);
+  Energy6 c1 = 4.*sqr(m*(W2-t2_));
+  Energy8 delta1 = (Q+t2_-4.*m*W-W2)*(Q+t2_+4.*m*W-W2)*(sqr(Q)-16.*m2*t2_-2.*Q*t2_+sqr(t2_)+2.*Q*W2-2.*t2_*W2+pow<4,1>(W));
+  Energy2 t1min = -0.5*(b1+sqrt(delta1))/a1;
+  Energy2 t1max = c1/a1/t1min;
+  thmin = lastCuts().minTij(mePartonData()[1], mePartonData()[3]);
+  if(thmin>abs(t1max)) t1max=-thmin;
+  if(abs(t1max)<Q2_1min_) t1max= -Q2_1min_;
+  if(abs(t1min)>Q2_1max_) t1min= -Q2_1max_;
+  if(t1max<t1min) return false;
+  t1_ = t1min*pow(t1max/t1min,r[1]);
+  double y1 = sqrt(1.-4.*m2/t1_);
+  jacobian(jacobian()*log(t1max/t1min)*t1_/sHat());
+  // then s1
+  Energy2 nu = 0.5*(W2-t1_-t2_);
+  Energy  K  = sqrt(sqr(nu)-t1_*t2_)/W;
+  double d1 = log(sHat()/(nu+K*W)*sqr(1.+beta)/((1.+y1)*(1.+y2)));
+  jacobian(jacobian()*d1);
+  Energy2 X1 = (nu+K*W)*(1.+y1)*exp(d1*r[2]);
+  Energy2 s1 = 0.5*X1+m2+t2_+2.*m2*t2_/X1;
+  // finally s2
+  Energy6 G3 = pow<6,1>(m) - 2.*sqr(m2)*s1 + sHat()*t2_*(sHat()-s1+t2_) + m2*(sqr(s1)-3.*sHat()*t2_);
+  Energy6 G4 = sqr(m2)*t1_ + t1_*(sqr(s1)+t2_*W2+s1*(t1_-t2_-W2))
+    - m2*(2.*s1*t1_ - sqr(t2_-W2) + t1_*(t2_ + W2));
+  auto Delta = 16.*G3*G4;
+  Energy6 rDelta = sqrt(Delta);
+  Energy4 a = sqr(s1-t2_-m2)-4.*m2*t2_;
+  Energy6 b = -2.*pow<6,1>(m) + 4.*sqr(m2)*s1 - 2.*m2*sqr(s1) + 2*sqr(m2)*t1_ - 2.*m2*sHat()*t1_
+    + 2.*sHat()*s1*t1_ - 2*sqr(s1)*t1_ + 8.*sqr(m2)*t2_ - 2*m2*sHat()*t2_ + 2*sHat()*s1*t2_ - 2*m2*t1_*t2_ + 2*sHat()*t1_*t2_
+    + 2*s1*t1_*t2_ - 2*m2*sqr(t2_) - 2*sHat()*sqr(t2_) - 4*sqr(m2)*W2 + 2*m2*sHat()*W2 + 4*m2*s1*W2
+    - 2*sHat()*s1*W2 + 2*sHat()*t2_*W2;
+  Energy2 s2 = -0.5/a*(b+rDelta*cos(Constants::pi*r[3]));
+  // now generate the momenta
+  // Energies and maginitudes of the momenta
+  Energy E1 = 0.5*(sHat()+m2-s2)/rS; Energy P1 = sqrt(sqr(E1)-m2);
+  Energy E2 = 0.5*(sHat()+m2-s1)/rS; Energy P2 = sqrt(sqr(E2)-m2);
+  Energy EX = 0.5*(s1+s2-2*m2)/rS  ; Energy PX = sqrt(sqr(EX)-W2);
+  // angle wrt beams
+  // e-
+  Energy6 D1 = 0.25*(-pow<6,1>(m)+ 2*sqr(m2)*s2-sHat()*t1_*(sHat()-s2+t1_)-sqr(m)*(sqr(s2) - 3.*sHat()*t1_));
+  double sTheta1 = 2.*sqrt(D1)/sHat()/beta/P1;
+  double cTheta1 = 0.5*(sHat()-s2+2.*t1_-3.*m2)/beta/rS/P1;
+  double theta1 = asin(sTheta1);
+  cHalf1_ = cos(0.5*theta1);
+  sHalf1_ = sin(0.5*theta1);
+  if(cTheta1<0.) {
+    swap(cHalf1_,sHalf1_);
+    cTheta1=-sqrt(1.-sqr(sTheta1));
+  }
+  else
+    cTheta1=sqrt(1.-sqr(sTheta1));
+  // e+
+  Energy6 D3 = -0.25*G3;
+  double sTheta2 = 2.*sqrt(D3)/sHat()/beta/P2;
+  double cTheta2 =-0.5*(sHat()-s1+2.*t2_-3.*m2)/beta/rS/P2;
+  double theta2 = asin(sTheta2);
+  cHalf2_ = cos(0.5*theta2);
+  sHalf2_ = sin(0.5*theta2);
+  if(cTheta2<0.) {
+    swap(cHalf2_,sHalf2_);
+    cTheta2=-sqrt(1.-sqr(sTheta2));
+  }
+  else
+    cTheta2=sqrt(1.-sqr(sTheta2));
+  // Energy6 D2 = 0.25*(-sqr(m2)*t2_ + m2*(2*s2*t2_ - sqr(t1_-W2) + t2_*(t1_ + W2)) - t2_*(sqr(s2) + t1_*W2 - s2*(t1_ - t2_ + W2)));
+  // hadronic system
+  Energy6 D6 = -0.25*m2*(s1-m2)*(s2-m2)
+    + 0.125*sHat()*((-m2 + s2 - t1_)*(-m2 + s1 - t2_) + t1_*t2_ - (sHat()-4*m2)*(W2-t1_-t2_));
+  Energy6 D5 = D1+D3+2.*D6;
+  if(D5<ZERO) return false;
+  double sThetaX = 2.*sqrt(max(ZERO,D5))/sHat()/beta/PX;
+  double cThetaX = 0.5*(s2-s1+2.*t2_-2.*t1_)/beta/rS/PX;
+  // azimuths
+  auto Delta4 = -Delta/64./a*sqr(sin(r[3]*Constants::pi));
+  if(Delta4>ZERO) return false;
+  double sPhi1 = 2.*sqrt(max(ZERO,-Delta4))/sHat()/beta/PX/sThetaX/P1/sTheta1;
+  double cPhi1 = (D1+D6)/sqrt(D1*D5);
+  double sPhi2 =-2.*sqrt(-Delta4)/sHat()/beta/PX/sThetaX/P2/sTheta2;
+  double cPhi2 = (D3+D6)/sqrt(D3*D5);
+  // rotation of the system
+  double phi = Constants::twopi*UseRandom::rnd();
+  double cPhi = cos(phi), sPhi = sin(phi);
+  phi1_ = atan2(sPhi1,cPhi1)+phi;
+  phi2_ = atan2(sPhi2,cPhi2)+phi;
+  // set the momenta
+  meMomenta()[2].setE(E1);
+  meMomenta()[3].setE(E2);
+  meMomenta()[2].setX( P1*sTheta1*(cPhi1*cPhi-sPhi1*sPhi));
+  meMomenta()[3].setX( P2*sTheta2*(cPhi2*cPhi-sPhi2*sPhi));
+  meMomenta()[2].setY( P1*sTheta1*(cPhi1*sPhi+sPhi1*cPhi));
+  meMomenta()[3].setY( P2*sTheta2*(cPhi2*sPhi+sPhi2*cPhi));
+  meMomenta()[2].setZ(P1*cTheta1);
+  meMomenta()[3].setZ(P2*cTheta2);
+  Lorentz5Momentum pX(-PX*sThetaX*cPhi,-PX*sThetaX*sPhi, PX*cThetaX,EX,W);
+  // momentum conservation test
+  Lorentz5Momentum ptotal;
+  for(unsigned int ix=0;ix<4;++ix) {
+    if(ix<2) ptotal -=meMomenta()[ix];
+    else     ptotal +=meMomenta()[ix];
+  }
+  ptotal+=pX;
+  //double test = (sqr(ptotal.x())+sqr(ptotal.y())+sqr(ptotal.z())+sqr(ptotal.t()))/sHat();
+  if(meMomenta().size()==5) {
+    meMomenta()[4] = pX;
+  }
+  else {
+    vector<Lorentz5Momentum> pout(meMomenta().size()-4);
+    tcPDVector tout(mePartonData().begin()+4,mePartonData().end());
+    double jac = amp_->generateKinematics(r+5,W2,pout,tout);
+    Boost bv = pX.boostVector();
+    for(unsigned int ix=0;ix<pout.size();++ix)
+      meMomenta()[ix+4] = pout[ix].boost(bv);
+    jacobian(pow(Constants::twopi,3)*jac*jacobian());
+  }
+  // check the cuts
+  vector<LorentzMomentum> out(meMomenta().size()-2);
+  tcPDVector tout(meMomenta().size()-2);
+  for(unsigned int ix=0;ix<meMomenta().size()-2;++ix) {
+    out [ix] = meMomenta()   [2+ix];
+    tout[ix] = mePartonData()[2+ix];
+  }
+  return lastCuts().passCuts(tout, out, mePartonData()[0], mePartonData()[1]);
+}
+
+double MEff2ffX::me2() const {
+  // calculate the leptonic currents
+  vector<VectorWaveFunction> current1 =  firstCurrent(mePartonData()[0],meMomenta()[0],meMomenta()[2]);
+  vector<VectorWaveFunction> current2 = secondCurrent(mePartonData()[1],meMomenta()[1],meMomenta()[3]);
+  DVector save;
+  double output = amp_->me2(current1,current2,t1_,t2_,sHat(),
+			    vector<Lorentz5Momentum>(meMomenta().begin()+4,meMomenta().end()),
+			    cPDVector(mePartonData().begin()+4,mePartonData().end()),save);
+  meInfo(save);
+  return output;
+}
+
+CrossSection MEff2ffX::dSigHatDR() const {
+  return 0.5/pow(Constants::twopi,5)*sqr(hbarc)*me2()*jacobian()/sHat()*sqr(sHat()*UnitRemoval::InvE2);
+}
+
+Selector<MEBase::DiagramIndex>
+MEff2ffX::diagrams(const DiagramVector & diags) const {
+  Selector<DiagramIndex> sel;
+  for ( DiagramIndex i = 0; i < diags.size(); ++i ) {
+    unsigned int id = abs(diags[i]->id())-1;
+    if(id<meInfo().size())
+      sel.insert(meInfo()[0], i);
+    else if ( meInfo().empty() ) sel.insert(1., i);
+    else
+      assert(false);
+  }
+  return sel;
+}
+
+Selector<const ColourLines *>
+MEff2ffX::colourGeometries(tcDiagPtr diag) const {
+  return amp_->colourGeometries(1,mePartonData(),diag);
+}
+
+IBPtr MEff2ffX::clone() const {
+  return new_ptr(*this);
+}
+
+IBPtr MEff2ffX::fullclone() const {
+  return new_ptr(*this);
+}
+
+void MEff2ffX::persistentOutput(PersistentOStream & os) const {
+  os << FFPVertex_ << gamma_ << amp_ << currentMode_
+     << ounit(Q2_1min_,GeV2) << ounit(Q2_1max_,GeV2)
+     << ounit(Q2_2min_,GeV2) << ounit(Q2_2max_,GeV2)
+     << ounit(mHatMin_,GeV) << formFactor_;
+}
+
+void MEff2ffX::persistentInput(PersistentIStream & is, int) {
+  is >> FFPVertex_ >> gamma_ >> amp_ >> currentMode_
+     >> iunit(Q2_1min_,GeV2) >> iunit(Q2_1max_,GeV2)
+     >> iunit(Q2_2min_,GeV2) >> iunit(Q2_2max_,GeV2) >> iunit(mHatMin_,GeV)
+     >> formFactor_;
+}
+
+void MEff2ffX::doinit() {
+  HwMEBase::doinit();
+  // cast the SM pointer to the Herwig SM pointer
+  tcHwSMPtr hwsm= dynamic_ptr_cast<tcHwSMPtr>(standardModel());
+  FFPVertex_ = hwsm->vertexFFP();
+  gamma_ = getParticleData(ParticleID::gamma);
+
+  vector<Energy2> q2 = {0.*GeV2,1.*GeV2,2.*GeV2,3.*GeV2,4.*GeV2,100.*GeV2};
+  vector<double>  ff = {1.,1.,1.,1.,1.,1.};
+  formFactor_ = make_InterpolatorPtr(ff,q2,3);
+}
+
+// The following static variable is needed for the type
+// description system in ThePEG.
+DescribeClass<MEff2ffX,HwMEBase>
+describeHerwigMEff2ffX("Herwig::MEff2ffX", "HwMEGammaGamma.so");
+
+void MEff2ffX::Init() {
+
+  static ClassDocumentation<MEff2ffX> documentation
+    ("The MEff2ffX class implements e+e- -> e+e- gamma gamma processes with"
+     " gamma gamma-X via the GammaGammaAmplitude");
+
+  static Parameter<MEff2ffX,Energy2> interfaceQ2_1Min
+    ("Q2_1Min",
+     "The minimum value of Q2 for the off-shell photon from the electron",
+     &MEff2ffX::Q2_1min_, GeV2, 0.*GeV2, 0.0*GeV2, Constants::MaxEnergy2,
+     false, false, Interface::limited);
+
+  static Parameter<MEff2ffX,Energy2> interfaceQ2_1Max
+    ("Q2_1Max",
+     "The maximum value of Q2 for the off-shell photon from the electron",
+     &MEff2ffX::Q2_1max_, GeV2, 0.*GeV2, 0.0*GeV2, Constants::MaxEnergy2,
+     false, false, Interface::limited);
+
+  static Parameter<MEff2ffX,Energy2> interfaceQ2_2Min
+    ("Q2_2Min",
+     "The minimum value of Q2 for the off-shell photon from the electron",
+     &MEff2ffX::Q2_2min_, GeV2, 0.*GeV2, 0.0*GeV2, Constants::MaxEnergy2,
+     false, false, Interface::limited);
+
+  static Parameter<MEff2ffX,Energy2> interfaceQ2_2Max
+    ("Q2_2Max",
+     "The maximum value of Q2 for the off-shell photon from the electron",
+     &MEff2ffX::Q2_2max_, GeV2, 0.*GeV2, 0.0*GeV2, Constants::MaxEnergy2,
+     false, false, Interface::limited);
+
+  static Reference<MEff2ffX,GammaGammaAmplitude> interfaceAmplitude
+    ("Amplitude",
+     "The gamma gamma -> X amplitude",
+     &MEff2ffX::amp_, false, false, true, false, false);
+
+  static Switch<MEff2ffX,unsigned int> interfaceCurrentMode
+    ("CurrentMode",
+     "Approximation in which to calculate the electron and position currents",
+     &MEff2ffX::currentMode_, 0, false, false);
+  static SwitchOption interfaceCurrentModeFull
+    (interfaceCurrentMode,
+     "Full",
+     "Use the full result, calculated to be numerically stable in the collineart limit",
+     0);
+  static SwitchOption interfaceCurrentModeEquivalentPhoton
+    (interfaceCurrentMode,
+     "EquivalentPhoton",
+     "Use the equivalent photon approximation",
+     1);
+  static SwitchOption interfaceCurrentModeEquivalentPhotonNoSpin
+    (interfaceCurrentMode,
+     "EquivalentPhotonNoSpin",
+     "Use the equivalent photon approximation, neglecting spin correlations",
+     2);
+
+  static Parameter<MEff2ffX,Energy> interfaceMHatMin
+    ("MHatMin",
+     "The minimum Mhat for the core process",
+     &MEff2ffX::mHatMin_, GeV, ZERO, 0.0*GeV, 0*GeV,
+     false, false, Interface::lowerlim);
+
+}
+
+vector<VectorWaveFunction> MEff2ffX::firstCurrent(tcPDPtr inPart,
+						  const Lorentz5Momentum & pin,
+						  const Lorentz5Momentum & pout) const {
+  double ee = FFPVertex_->electroMagneticCoupling(ZERO);
+  Lorentz5Momentum pGamma = pin-pout;
+  // form factors
+  Energy m = inPart->mass();
+  double F1(0.),F2(0.);
+  if(abs(inPart->id())==ParticleID::eminus) {
+    F1 = 1.;
+  }
+  else if(abs(inPart->id())==ParticleID::pplus) {
+    // defining the form factors F1 and F2 from Ginzburg
+    Energy2 q02 = 0.71*GeV2;
+    double Ge = 1/sqr(1-t1_/q02);
+    double Gm = Ge*sqrt(7.78);
+    double tau = -t1_/4./sqr(m);
+    F1 = (Ge + tau*Gm)/(1.+ tau);
+    F2 = (Gm - Ge)/(1 + tau);
+  }
+  else {
+    LorentzPolarizationVector current = (*formFactor_)(t1_)*UnitRemoval::E/t1_*ee*(inPart->iCharge()/3)*(pin+pout);
+    vector<VectorWaveFunction> output;
+    output.push_back(VectorWaveFunction(pGamma,gamma_,current));
+    return output;
+  }
+  // calculation of the current
+  Complex II(0.,1.);
+  Complex phase = exp(II*phi1_);
+  Energy Ea = pin.t();
+  // full current, safe in small x limit
+  vector<LorentzPolarizationVector> current(4);
+  if(currentMode_==0) {
+    double mr2 = sqr(m/Ea);
+    double x = pout.t()/Ea;
+    double b = sqrt(1.-mr2), b1 = sqrt(1-mr2/sqr(x)), bb1=(1.+b)*(1.+b1);
+    double fact1 = (F1+F2)*2.*Ea*sqrt(x)*sHalf1_/sqrt(bb1)/t1_*UnitRemoval::E*ee;
+    double fact2 = (F1+F2)*m/sqrt(x)            /sqrt(bb1)/t1_*UnitRemoval::E*ee;
+    // F1 piece
+    current[0] = fact1*LorentzPolarizationVector(0.5*phase*(bb1-mr2/x)+b1*sqr(cHalf1_)*(mr2+bb1*x)*cos(phi1_)/(1.-x),
+						 -0.5*II*phase*(bb1-mr2/x)+b1*sqr(cHalf1_)*(mr2+bb1*x)*sin(phi1_)/(1.-x),
+						 cHalf1_*mr2*(1.+b1-(1.+b)/x)/(sHalf1_*(1.-x))-b1*cHalf1_*sHalf1_*(mr2+bb1*x)/(1.-x),0);
+    current[1] = fact2*LorentzPolarizationVector(-cHalf1_*(1 +b-(1 +b1)*x)+2.*b1*cHalf1_*sqr(sHalf1_)*x*(1.+b+(1.+b1)*x)*cos(phi1_)/(phase*(1.-x)),
+						 II*cHalf1_*(1.+b-(1.+b1)*x)+2.*b1*cHalf1_*sqr(sHalf1_)*x*(1.+b+(1.+b1)*x)*sin(phi1_)/(phase*(1.-x)),
+						 -2.*sHalf1_*x*((1.+b)*(1.+b1*sqr(sHalf1_))-(1.+b1)*(1.-b1*sqr(sHalf1_))*x)/(phase*(1.-x)),0);
+    current[2] = fact2*LorentzPolarizationVector(cHalf1_   *(1.+b-(1.+b1)*x)-2.*b1*cHalf1_*phase*sqr(sHalf1_)*x*(1.+b+(1.+b1)*x)*cos(phi1_)/(1.-x),
+						 II*cHalf1_*(1.+b-(1.+b1)*x)-2.*b1*cHalf1_*phase*sqr(sHalf1_)*x*(1.+b+(1.+b1)*x)*sin(phi1_)/(1.-x),
+						 2.*phase*sHalf1_*x*((1.+b)*(1.+b1*sqr(sHalf1_))-(1.+b1)*(1.-b1*sqr(sHalf1_))*x)/(1.-x),0);
+    current[3] = fact1*LorentzPolarizationVector(0.5*(bb1-mr2/x)/phase+b1*sqr(cHalf1_)*(mr2+bb1*x)*cos(phi1_)/(1.-x),
+						 0.5*II*(bb1-mr2/x)/phase+b1*sqr(cHalf1_)*(mr2+bb1*x)*sin(phi1_)/(1.-x),
+						 cHalf1_*mr2*(1.+b1-(1.+b)/x)/(sHalf1_*(1.-x))-b1*cHalf1_*sHalf1_*(mr2+bb1*x)/(1.-x),0);
+    // F2 piece if non-zero
+    if(F2!=0) {
+      double fact3 = F2*2.*    Ea *sqrt(x)*cHalf1_/sqrt(bb1)*(1.+b+x*(1.+b1))/(1.-x)/t1_*UnitRemoval::E*ee;
+      double fact4 = F2*   sqr(Ea)*(mr2+bb1*x)/m/sqrt(x)*sHalf1_/sqrt(bb1)/(1.-x)/t1_*UnitRemoval::E*ee;
+      current[0] -= fact3*LorentzPolarizationVector(b1*cHalf1_*sHalf1_*cos(phi1_),b1*cHalf1_*sHalf1_*sin(phi1_),
+						    -b1*sqr(sHalf1_)-0.5*mr2*(1.-x)*(1.+x)/((b+b1)*sqr(x)),0.);
+      current[1] -= fact4/phase*LorentzPolarizationVector(2.*b1*cHalf1_*sHalf1_*x*cos(phi1_),
+							  2.*b1*cHalf1_*sHalf1_*x*sin(phi1_),
+							  -x*(2.*b1*sqr(sHalf1_)+mr2*(1.-x)*(1.+x)/((b+b1)*sqr(x))),0);
+      current[2] -= fact4*phase*LorentzPolarizationVector(-2.*b1*cHalf1_*sHalf1_*x*cos(phi1_),
+							  -2.*b1*cHalf1_*sHalf1_*x*sin(phi1_),
+							  x*(2.*b1*sqr(sHalf1_)+mr2*(1.-x)*(1.+x)/((b+b1)*sqr(x))),0.);
+      current[3] -= fact3*LorentzPolarizationVector(b1*cHalf1_*sHalf1_*cos(phi1_),b1*cHalf1_*sHalf1_*sin(phi1_),
+						    -b1*sqr(sHalf1_)-0.5*mr2*(1.-x)*(1.+x)/((b+b1)*sqr(x)),0.);
+    }
+  }
+  // approximate modes
+  else if(currentMode_<=2) {
+    Lorentz5Momentum p = pin;
+    Lorentz5Momentum n(ZERO,ZERO,-Ea,Ea);
+    double z = (n*pout)/(n*p);
+    Energy2 pT2 = -z*t1_-sqr(1-z)*sqr(m);
+    if(pT2<ZERO) pT2=ZERO;
+    Energy pT = sqrt(pT2);
+    // Equivalent Photon (with spin correlations)
+    if(currentMode_==1) {
+      double fact = ee*Ea*UnitRemoval::E/t1_;
+      // normal piece
+      double fact1 = fact*(F1+F2)*pT/Ea/sqrt(z)/(1.-z);
+      double fact2 = fact*(F1+F2)* m/Ea/sqrt(z)*(1.-z);
+      current[0] = fact1*LorentzPolarizationVector(phase+z/phase,-II*(phase-z/phase),0., 0.);
+      current[1] = fact2*LorentzPolarizationVector(-1.,II,0.,0.);
+      current[2] = fact2*LorentzPolarizationVector( 1.,II,0.,0.);
+      current[3] = fact1*LorentzPolarizationVector(1./phase+z*phase,II*(1./phase-phase*z),0.,0.);
+      // F2 piece if non-zero
+      if(F2!=0) {
+	double fact3 = fact*F2*    pT /Ea  *(1.+z)/(1.-z)/sqrt(z);
+	double fact4 = fact*F2*sqr(pT)/Ea/m       /(1.-z)/sqrt(z);
+	current[0] -= fact3      *LorentzPolarizationVector( cos(phi1_), sin(phi1_),0,0);
+	current[1] -= fact4/phase*LorentzPolarizationVector( cos(phi1_), sin(phi1_),0,0);
+	current[2] -= fact4*phase*LorentzPolarizationVector(-cos(phi1_),-sin(phi1_),0,0);
+	current[3] -= fact3      *LorentzPolarizationVector( cos(phi1_), sin(phi1_),0,0);
+      }
+    }
+    // no spin correlations
+    else if(currentMode_==2) {
+      Energy2 m2=sqr(m);
+      double ort=sqrt(0.5);
+      double fact = ort*ee*UnitRemoval::E/t1_*
+	sqrt(2.*pT2*((4.*sqr(F1))/sqr(1.-z) + (2.*sqr(F1)+4.*F1*F2+3.*sqr(F2))/z)
+	     +2.*sqr(F2)*sqr(pT2)/(m2*sqr(1.-z)*z)
+	     +4.*sqr(F1+F2)*m2*sqr(1.-z)/z);
+      current.resize(2);
+      current[0] = fact*ort*LorentzPolarizationVector( 1,-II,0.,0.);
+      current[1] = fact*ort*LorentzPolarizationVector(-1,-II,0.,0.);
+    }
+  }
+  // no other option
+  else {
+    assert(false);
+  }
+  // test code
+  // SpinorWaveFunction    ein (pin,inPart,incoming);
+  // SpinorBarWaveFunction eout(pout,inPart,outgoing);
+  // vector<SpinorWaveFunction>    fin;
+  // vector<SpinorBarWaveFunction> fout;
+  // for(unsigned int ix=0;ix<2;++ix) {
+  //   ein .reset(ix); fin .push_back(ein );
+  //   eout.reset(ix); fout.push_back(eout);
+  // }
+  // cerr << "testing +z dirn " << inPart->PDGName() << " " << currentMode_ << " " << F1 << " " << F2 << "\n";
+  // for(unsigned int ih1=0;ih1<2;++ih1) {
+  //   for(unsigned int ih2=0;ih2<2;++ih2) {
+  //     LorentzPolarizationVector test  = (F1+F2)*ee/t1_*UnitRemoval::E2*fin[ih1].wave().vectorCurrent(fout[ih2].wave());
+  //     test -= F2*(pin+pout)/2./m*ee/t1_*UnitRemoval::E2*fin[ih1].wave().scalar(fout[ih2].wave());
+  //     test -= test.t()*pGamma/pGamma.t();
+  //     cerr << "testing in current\n"
+  //   	   << ih1 << " " << ih2 << " " << test.x() << " " << test.y() << " " << test.z() << " " << test.t() << "\n"
+  //   	   << ih1 << " " << ih2 << " " << current[2*ih1+ih2].x() << " " << current[2*ih1+ih2].y() << " "
+  //   	   << current[2*ih1+ih2].z() << " " << current[2*ih1+ih2].t() << "\n"
+  //    	   << (test.x()-current[2*ih1+ih2].x())/(test.x()+current[2*ih1+ih2].x()) << " "
+  //    	   << (test.y()-current[2*ih1+ih2].y())/(test.y()+current[2*ih1+ih2].y()) << " "
+  //    	   << (test.z()-current[2*ih1+ih2].z())/(test.z()+current[2*ih1+ih2].z()) << " ";
+  //     if(current[2*ih1+ih2].t()!=0.)
+  //   	cerr << (test.t()-current[2*ih1+ih2].t())/(test.t()+current[2*ih1+ih2].t());
+  //     cerr << "\n";
+  //   }
+  // }
+  // return the currents
+  vector<VectorWaveFunction> output; output.reserve(4);
+  for(unsigned int ix=0;ix<4;++ix)
+    output.push_back(VectorWaveFunction(pGamma,gamma_,current[ix]));
+  return output;
+}
+
+vector<VectorWaveFunction> MEff2ffX::secondCurrent(tcPDPtr inPart,
+						   const Lorentz5Momentum & pin,
+						   const Lorentz5Momentum & pout) const {
+  Lorentz5Momentum pGamma = pin-pout;
+  double ee = FFPVertex_->electroMagneticCoupling(ZERO);
+  // form factors
+  Energy m = inPart->mass();
+  double F1(0.),F2(0.);
+  if(abs(inPart->id())==ParticleID::eminus) {
+    F1 = 1.;
+  }
+  else if(abs(inPart->id())==ParticleID::pplus) {
+    //defining the form factors F1 and F2 from Ginzburg
+    Energy2 q02 = 0.71*GeV2;
+    double Ge = 1/sqr(1-t2_/q02);
+    double Gm = Ge*sqrt(7.78);
+    double tau = -t2_/4./sqr(m);
+    F1 = (Ge + tau*Gm)/(1.+ tau);
+    F2 = (Gm - Ge)/(1 + tau);
+  }
+  else {
+    LorentzPolarizationVector current = (*formFactor_)(t2_)*UnitRemoval::E/t2_*ee*(inPart->iCharge()/3)*(pin+pout);
+    vector<VectorWaveFunction> output;
+    output.push_back(VectorWaveFunction(pGamma,gamma_,current));
+    return output;
+  }
+  // calculation of the current
+  Complex II(0.,1.);
+  Complex phase = exp(II*phi2_);
+  Energy Ea = pin.t();
+  vector<LorentzPolarizationVector> current(4);
+  // full result stable for small pT and x->1
+  if(currentMode_==0) {
+    double mr2 = sqr(m/Ea);
+    double x = pout.t()/Ea;
+    double b = sqrt(1.-mr2), b1 = sqrt(1-mr2/sqr(x)), bb1=(1.+b)*(1.+b1);
+    double fact1 = (F1+F2)*2.*Ea*sqrt(x)*cHalf2_/sqrt(bb1)/t2_*UnitRemoval::E*ee;
+    double fact2 = (F1+F2)*m/sqrt(x)            /sqrt(bb1)/t2_*UnitRemoval::E*ee;
+    current[0] = fact1*LorentzPolarizationVector(0.5*(bb1-mr2/x)   +b1*phase*sqr(sHalf2_)*(mr2+bb1*x)*cos(phi2_)/(1.-x),
+						 0.5*II*(bb1-mr2/x)+b1*phase*sqr(sHalf2_)*(mr2+bb1*x)*sin(phi2_)/(1.-x),
+						 phase*(mr2*sHalf2_*(1.+b-(1.+b1)*x)/cHalf2_/x+b1*cHalf2_*sHalf2_*(mr2+bb1*x))/(1.-x),0);
+    current[1] = fact2*LorentzPolarizationVector(sHalf2_*(   (1.+b-(1.+b1)*x)/phase-2.*b1*sqr(cHalf2_)*x*(1.+b+(1.+b1)*x)*cos(phi2_)/(1.-x)),
+						 sHalf2_*(II*(1.+b-(1.+b1)*x)/phase-2.*b1*sqr(cHalf2_)*x*(1.+b+(1.+b1)*x)*sin(phi2_)/(1.-x)),
+						 -2.*cHalf2_*x*((1.+b)*(1.+b1*sqr(cHalf2_))-(1.+b1)*(1.-b1*sqr(cHalf2_))*x)/(1.-x),0.);
+    current[2] = fact2*LorentzPolarizationVector(sHalf2_*(  -phase*(1.+b-(1.+b1)*x)+2.*b1*sqr(cHalf2_)*x*(1.+b+(1.+b1)*x)*cos(phi2_)/(1.-x)),
+						 sHalf2_*(II*phase*(1.+b-(1.+b1)*x)+2.*b1*sqr(cHalf2_)*x*(1.+b+(1.+b1)*x)*sin(phi2_)/(1.-x)),
+						 2.*cHalf2_*x*((1.+b)*(1.+b1*sqr(cHalf2_))-(1.+b1)*(1.-b1*sqr(cHalf2_))*x)/(1.-x),0);
+    current[3] = fact1*LorentzPolarizationVector(0.5*(bb1-mr2/x)+b1*sqr(sHalf2_)*(mr2+bb1*x)*cos(phi2_)/phase/(1.-x),
+						 -0.5*II*(bb1-mr2/x)+b1*sqr(sHalf2_)*(mr2+bb1*x)*sin(phi2_)/phase/(1.-x),
+						 (mr2*sHalf2_*(1.+b-(1.+b1)*x)/x/cHalf2_+b1*cHalf2_*sHalf2_*(mr2+bb1*x))/phase/(1.-x),0.);
+    // F2 piece if non-zero
+    if(F2!=0) {
+      double fact3 = F2*2.*    Ea   *sqrt(x)*sHalf2_/sqrt(bb1)*(1.+b+x*(1.+b1))/(1.-x)/t2_*UnitRemoval::E*ee;
+      double fact4 = F2*   sqr(Ea)/m/sqrt(x)*cHalf2_/sqrt(bb1)*(mr2+bb1*x)     /(1.-x)/t2_*UnitRemoval::E*ee;
+      current[0] -= fact3*phase*LorentzPolarizationVector(b1*cHalf2_*sHalf2_*cos(phi2_),b1*cHalf2_*sHalf2_*sin(phi2_),
+							  b1*sqr(cHalf2_)+0.5*mr2*(1.-x)*(1.+x)/((b+b1)*sqr(x)),0);
+      current[1] -= fact4*      LorentzPolarizationVector(-2.*b1*cHalf2_*sHalf2_*x*cos(phi2_),
+							  -2.*b1*cHalf2_*sHalf2_*x*sin(phi2_),
+							  -x*(2.*b1*sqr(cHalf2_)+mr2*(1.-x)*(1.+x)/((b+b1)*sqr(x))),0.);
+      current[2] -= fact4*      LorentzPolarizationVector(2.*b1*cHalf2_*sHalf2_*x*cos(phi2_),
+							  2.*b1*cHalf2_*sHalf2_*x*sin(phi2_),
+							  x*(2.*b1*sqr(cHalf2_)+mr2*(1.-x)*(1.+x)/((b+b1)*sqr(x))),0.);
+      current[3] -= fact3/phase*LorentzPolarizationVector(b1*cHalf2_*sHalf2_*cos(phi2_),b1*cHalf2_*sHalf2_*sin(phi2_),
+							  b1*sqr(cHalf2_)+0.5*mr2*(1.-x)*(1.+x)/((b+b1)*sqr(x)),0);
+    }
+  }
+  // approximate modes
+  else if(currentMode_<=2) {
+    Lorentz5Momentum p = pin;
+    Lorentz5Momentum n(ZERO,ZERO,Ea,Ea);
+    double z = (n*pout)/(n*p);
+    Energy2 pT2 = -z*t2_-sqr(1-z)*sqr(m);
+    if(pT2<ZERO) pT2=ZERO;
+    Energy pT = sqrt(pT2);
+    // Equivalent Photon with spin correlations
+    if(currentMode_<=1) {
+      double fact = ee*Ea*UnitRemoval::E/t2_;
+      double fact1 = fact*(F1+F2)*pT/Ea/sqrt(z)/(1.-z);
+      double fact2 = fact*(F1+F2)*m /Ea/sqrt(z)*(1.-z);
+      current[0] = fact1      *LorentzPolarizationVector(1.+z*sqr(phase), II*(1.-z*sqr(phase)),0., 0.);
+      current[1] = fact2/phase*LorentzPolarizationVector( 1.,II,0.,0.);
+      current[2] = fact2*phase*LorentzPolarizationVector(-1.,II,0.,0.);
+      current[3] = fact1      *LorentzPolarizationVector(1.+z/sqr(phase),-II*(1.-z/sqr(phase)),0.,0.);
+      // F2 piece if non-zero
+      if(F2!=0) {
+	double fact1 = fact*F2*    pT *(1.+z)/(Ea  *(1.-z)*sqrt(z));
+	double fact2 = fact*F2*sqr(pT)       /(Ea*m*(1.-z)*sqrt(z));
+	current[0] -= fact1*phase*LorentzPolarizationVector( cos(phi2_), sin(phi2_),0,0);
+	current[1] -= fact2      *LorentzPolarizationVector(-cos(phi2_),-sin(phi2_),0,0);
+	current[2] -= fact2      *LorentzPolarizationVector( cos(phi2_), sin(phi2_),0,0);
+	current[3] -= fact1/phase*LorentzPolarizationVector( cos(phi2_), sin(phi2_),0,0);
+      }
+    }
+    // no spin correlations
+    else if(currentMode_==2) {
+      double ort=sqrt(0.5);
+      Energy2 m2=sqr(m);
+      double fact = ort*ee*UnitRemoval::E/t2_*
+	sqrt(2.*pT2*((4.*sqr(F1))/sqr(1.-z) + (2.*sqr(F1)+4.*F1*F2+3.*sqr(F2))/z)
+	     +2.*sqr(F2)*sqr(pT2)/(m2*sqr(1.-z)*z)
+	     +4.*sqr(F1+F2)*m2*sqr(1.-z)/z);
+      current.resize(2);
+      current[0] = fact*ort*LorentzPolarizationVector(-1,-II,0.,0.);
+      current[1] = fact*ort*LorentzPolarizationVector( 1,-II,0.,0.);
+    }
+  }
+  // no other option
+  else {
+    assert(false);
+  }
+  // test code
+  // SpinorWaveFunction    ein (pin,inPart,incoming);
+  // SpinorBarWaveFunction eout(pout,inPart,outgoing);
+  // vector<SpinorWaveFunction>    fin;
+  // vector<SpinorBarWaveFunction> fout;
+  // for(unsigned int ix=0;ix<2;++ix) {
+  //   ein .reset(ix); fin .push_back(ein );
+  //   eout.reset(ix); fout.push_back(eout);
+  // }
+  // cerr << "testing -z dirn " << inPart->PDGName() << " " << currentMode_ << " " << F1 << " " << F2 << "\n";
+  // for(unsigned int ih1=0;ih1<2;++ih1) {
+  //   for(unsigned int ih2=0;ih2<2;++ih2) {
+  //     LorentzPolarizationVector test  = (F1+F2)*ee/t2_*UnitRemoval::E2*fin[ih1].wave().vectorCurrent(fout[ih2].wave());
+  //     test -= F2*(pin+pout)/2./m*ee/t2_*UnitRemoval::E2*fin[ih1].wave().scalar(fout[ih2].wave());
+  //     test -= test.t()*pGamma/pGamma.t();
+  //     cerr << "testing in current\n"
+  //   	   << ih1 << " " << ih2 << " " << test.x() << " " << test.y() << " " << test.z() << " " << test.t() << "\n"
+  //   	   << ih1 << " " << ih2 << " " << current[2*ih1+ih2].x() << " " << current[2*ih1+ih2].y() << " "
+  //   	   << current[2*ih1+ih2].z() << " " << current[2*ih1+ih2].t() << "\n"
+  //    	   << (test.x()-current[2*ih1+ih2].x())/(test.x()+current[2*ih1+ih2].x()) << " "
+  //    	   << (test.y()-current[2*ih1+ih2].y())/(test.y()+current[2*ih1+ih2].y()) << " "
+  //    	   << (test.z()-current[2*ih1+ih2].z())/(test.z()+current[2*ih1+ih2].z()) << " ";
+  //     if(current[2*ih1+ih2].t()!=0.)
+  //   	cerr << (test.t()-current[2*ih1+ih2].t())/(test.t()+current[2*ih1+ih2].t());
+  //     cerr << "\n";
+  //   }
+  // }
+  // return the answer
+  vector<VectorWaveFunction> output; output.reserve(4);
+  for(unsigned int ix=0;ix<4;++ix)
+    output.push_back(VectorWaveFunction(pGamma,gamma_,current[ix]));
+  return output;
+}
+
+void MEff2ffX::constructVertex(tSubProPtr sub) {
+  // extract the particles in the hard process
+  tParticleVector hard;
+  hard.reserve(sub->outgoing().size()+2);
+  hard.push_back(sub->incoming().first);
+  hard.push_back(sub->incoming().second);
+  for(unsigned int ix=0;ix<sub->outgoing().size();++ix)
+    hard.push_back(sub->outgoing()[ix]);
+  // calculate the fermionic currents
+  vector<VectorWaveFunction> current1 =  firstCurrent(hard[0]->dataPtr(),hard[0]->momentum(),hard[2]->momentum());
+  vector<VectorWaveFunction> current2 = secondCurrent(hard[1]->dataPtr(),hard[1]->momentum(),hard[3]->momentum());
+  // wavefunctions for the fermions
+  vector<SpinorWaveFunction>    f1,f2;
+  vector<SpinorBarWaveFunction> a1,a2;
+  if(hard[0]->dataPtr()->iSpin()==PDT::Spin1Half) {
+    if(hard[0]->id()>0) {
+      SpinorWaveFunction   (f1,hard[0],incoming,false,true);
+      SpinorBarWaveFunction(a1,hard[2],outgoing,true,true);
+    }
+    else {
+      SpinorWaveFunction   (f1,hard[2],outgoing,true,true);
+      SpinorBarWaveFunction(a1,hard[0],incoming,false,true);
+    }
+  }
+  else {
+    ScalarWaveFunction(hard[0],incoming,false);
+    ScalarWaveFunction(hard[2],outgoing,true );
+  }
+  if(hard[1]->dataPtr()->iSpin()==PDT::Spin1Half) {
+    if(hard[1]->id()>0) {
+      SpinorWaveFunction   (f2,hard[1],incoming,false,true);
+      SpinorBarWaveFunction(a2,hard[3],outgoing,true,true);
+    }
+    else {
+      SpinorWaveFunction   (f2,hard[3],outgoing,true,true);
+      SpinorBarWaveFunction(a2,hard[1],incoming,false,true);
+    }
+  }
+  else {
+    ScalarWaveFunction(hard[1],incoming,false);
+    ScalarWaveFunction(hard[3],outgoing,true );
+  }
+  tParticleVector pTemp(hard.begin()+4,hard.end());
+  ProductionMatrixElement me = amp_->me(current1,current2,pTemp);
+  // construct the vertex
+  HardVertexPtr hardvertex=new_ptr(HardVertex());
+  // set the matrix element for the vertex
+  hardvertex->ME(me);
+  // set the pointers and to and from the vertex
+  for(unsigned int ix=0;ix<hard.size();++ix) {
+    hard[ix]->spinInfo()->productionVertex(hardvertex);
+  }
+}
diff --git a/MatrixElement/Gamma/MEff2ffX.h b/MatrixElement/Gamma/MEff2ffX.h
new file mode 100644
--- /dev/null
+++ b/MatrixElement/Gamma/MEff2ffX.h
@@ -0,0 +1,302 @@
+// -*- C++ -*-
+#ifndef Herwig_MEff2ffX_H
+#define Herwig_MEff2ffX_H
+//
+// This is the declaration of the MEff2ffX class.
+//
+
+#include "Herwig/MatrixElement/HwMEBase.h"
+#include "Herwig/Models/StandardModel/StandardModel.h"
+#include "Herwig/Utilities/Interpolator.h"
+#include "GammaGammaAmplitude.h"
+
+namespace Herwig {
+
+using namespace ThePEG;
+
+/**
+ * The MEff2ffX class implements the processes \f$e^+e^-\to e^+e^- \gamma\gamma\f$ followed by
+ * \f$\gamma\gamma\to X\f$ using the GammaGammaAmplitude class
+ *
+ * @see \ref MEff2ffXInterfaces "The interfaces"
+ * defined for MEff2ffX.
+ */
+class MEff2ffX: public HwMEBase {
+
+public:
+  
+  /**
+   * The default constructor.
+   */
+  MEff2ffX() : Q2_1min_(ZERO), Q2_1max_(Constants::MaxEnergy2),
+	       Q2_2min_(ZERO), Q2_2max_(Constants::MaxEnergy2),
+	       mHatMin_(ZERO),
+	       currentMode_(0)
+  {}
+  
+public:
+
+  /** @name Virtual functions required by the MEBase class. */
+  //@{
+  /**
+   * Return the order in \f$\alpha_S\f$ in which this matrix
+   * element is given.
+   */
+  virtual unsigned int orderInAlphaS() const {
+    return amp_->orderInAlphaS();
+  }
+
+  /**
+   * Return the order in \f$\alpha_{EW}\f$ in which this matrix
+   * element is given.
+   */
+  virtual unsigned int orderInAlphaEW() const {
+    return amp_->orderInAlphaS()+2;
+  }
+
+  /**
+   * The matrix element for the kinematical configuration
+   * previously provided by the last call to setKinematics(), suitably
+   * scaled by sHat() to give a dimension-less number.
+   * @return the matrix element scaled with sHat() to give a
+   * dimensionless number.
+   */
+  virtual double me2() const;
+
+  /**
+   * Return the scale associated with the last set phase space point.
+   */
+  virtual Energy2 scale() const;
+
+  /**
+   * Set the typed and momenta of the incoming and outgoing partons to
+   * be used in subsequent calls to me() and colourGeometries()
+   * according to the associated XComb object. If the function is
+   * overridden in a sub class the new function must call the base
+   * class one first.
+   */
+  virtual void setKinematics();
+
+  /**
+   * The number of internal degrees of freedom used in the matrix
+   * element.
+   */
+  virtual int nDim() const;
+
+  /**
+   * Generate internal degrees of freedom given nDim() uniform
+   * random numbers in the interval \f$ ]0,1[ \f$. To help the phase space
+   * generator, the dSigHatDR should be a smooth function of these
+   * numbers, although this is not strictly necessary.
+   * @param r a pointer to the first of nDim() consecutive random numbers.
+   * @return true if the generation succeeded, otherwise false.
+   */
+  virtual bool generateKinematics(const double * r);
+
+  /**
+   * Return the matrix element squared differential in the variables
+   * given by the last call to generateKinematics().
+   */
+  virtual CrossSection dSigHatDR() const;
+
+  /**
+   * Add all possible diagrams with the add() function.
+   */
+  virtual void getDiagrams() const;
+
+  /**
+   * Get diagram selector. With the information previously supplied with the
+   * setKinematics method, a derived class may optionally
+   * override this method to weight the given diagrams with their
+   * (although certainly not physical) relative probabilities.
+   * @param dv the diagrams to be weighted.
+   * @return a Selector relating the given diagrams to their weights.
+   */
+  virtual Selector<DiagramIndex> diagrams(const DiagramVector & dv) const;
+
+  /**
+   * Return a Selector with possible colour geometries for the selected
+   * diagram weighted by their relative probabilities.
+   * @param diag the diagram chosen.
+   * @return the possible colour geometries weighted by their
+   * relative probabilities.
+   */
+  virtual Selector<const ColourLines *>
+  colourGeometries(tcDiagPtr diag) const;
+
+  /**
+   *  Construct the vertex of spin correlations.
+   */
+  virtual void constructVertex(tSubProPtr);
+  //@}
+
+protected:
+
+  /**
+   * Calculation of the leptonic currents
+   */
+  //@{
+  /**
+   *  Calculation of the current in the positive direction
+   */
+  vector<VectorWaveFunction> firstCurrent(tcPDPtr inPart,
+					  const Lorentz5Momentum & pin,
+					  const Lorentz5Momentum & pout) const;
+  
+  /**
+   *  Calculation of the current in the negative direction
+   */
+  vector<VectorWaveFunction> secondCurrent(tcPDPtr inPart,
+					   const Lorentz5Momentum & pin,
+					   const Lorentz5Momentum & pout) const;
+  //@}
+
+
+public:
+
+  /** @name Functions used by the persistent I/O system. */
+  //@{
+  /**
+   * Function used to write out object persistently.
+   * @param os the persistent output stream written to.
+   */
+  void persistentOutput(PersistentOStream & os) const;
+
+  /**
+   * Function used to read in object persistently.
+   * @param is the persistent input stream read from.
+   * @param version the version number of the object when written.
+   */
+  void persistentInput(PersistentIStream & is, int version);
+  //@}
+
+  /**
+   * The standard Init function used to initialize the interfaces.
+   * Called exactly once for each class by the class description system
+   * before the main function starts or
+   * when this class is dynamically loaded.
+   */
+  static void Init();
+
+protected:
+
+  /** @name Standard Interfaced functions. */
+  //@{
+  /**
+   * Initialize this object after the setup phase before saving an
+   * EventGenerator to disk.
+   * @throws InitException if object could not be initialized properly.
+   */
+  virtual void doinit();
+  //@}
+
+protected:
+
+  /** @name Clone Methods. */
+  //@{
+  /**
+   * Make a simple clone of this object.
+   * @return a pointer to the new object.
+   */
+  virtual IBPtr clone() const;
+
+  /** Make a clone of this object, possibly modifying the cloned object
+   * to make it sane.
+   * @return a pointer to the new object.
+   */
+  virtual IBPtr fullclone() const;
+  //@}
+
+private:
+
+  /**
+   * The assignment operator is private and must never be called.
+   * In fact, it should not even be implemented.
+   */
+  MEff2ffX & operator=(const MEff2ffX &) = delete;
+
+private:
+
+  /**
+   *   fermion-fermion-photon vertex
+   */
+  AbstractFFVVertexPtr FFPVertex_;
+
+  /**
+   *  Pointer to the particle data object for the photon
+   */
+  PDPtr gamma_;
+
+  /**
+   *  Pointer to the amplitude for the \f$\gamma\gamma$ process
+   */
+  GammaGammaAmpPtr amp_;
+
+  /**
+   *  Storage of the nucleon form factor
+   */
+  Interpolator<double,Energy2>::Ptr formFactor_;
+
+private:
+
+  /**
+   *   Cuts
+   */
+  //@{
+  /**
+   *  Minimum value of \f$Q_1^2\f$
+   */
+  Energy2 Q2_1min_;
+  
+  /**
+   *  Maximum value of \f$Q_1^2\f$
+   */
+  Energy2 Q2_1max_;
+  
+  /**
+   *  Minimum value of \f$Q_2^2\f$
+   */
+  Energy2 Q2_2min_;
+  
+  /**
+   *  Maximum value of \f$Q_2^2\f$
+   */
+  Energy2 Q2_2max_;
+
+  /**  
+   * Minimum \f$\hat{m}\f$ for the core process
+   */
+  Energy mHatMin_;
+  //@}
+
+private:
+
+  /**
+   *  Kinematic quantities stored for accuracy
+   */
+  //@{
+  /**
+   *  Outgoing electron
+   */
+  double cHalf1_,sHalf1_,phi1_;
+  Energy2 t1_;
+  
+  /**
+   *  Outgoing positron
+   */
+  double cHalf2_,sHalf2_,phi2_;
+  Energy2 t2_;
+  //@}
+
+private:
+
+  /**
+   * Switch for the current approximation
+   */
+  unsigned int currentMode_;
+
+};
+
+}
+
+#endif /* Herwig_MEff2ffX_H */
diff --git a/MatrixElement/Gamma/Makefile.am b/MatrixElement/Gamma/Makefile.am
--- a/MatrixElement/Gamma/Makefile.am
+++ b/MatrixElement/Gamma/Makefile.am
@@ -1,11 +1,17 @@
 pkglib_LTLIBRARIES = HwMEGammaGamma.la HwMEGammaHadron.la
 
 HwMEGammaGamma_la_SOURCES = \
-MEGammaGamma2ff.cc MEGammaGamma2ff.h \
 MEGammaGamma2WW.cc MEGammaGamma2WW.h \
-MEGammaGamma2PiPi.cc MEGammaGamma2PiPi.h 
+MEff2ffX.cc MEff2ffX.h \
+MEGammaGamma2X.cc MEGammaGamma2X.h \
+GammaGammaAmplitude.h GammaGammaAmplitude.fh GammaGammaAmplitude.cc \
+GammaGamma2ScalarAmplitude.h  GammaGamma2ScalarAmplitude.cc \
+GammaGamma2PseudoScalarAmplitude.h  GammaGamma2PseudoScalarAmplitude.cc \
+GammaGamma2TensorAmplitude.h  GammaGamma2TensorAmplitude.cc \
+GammaGamma2PiPiAmplitude.h  GammaGamma2PiPiAmplitude.cc \
+GammaGamma2ffAmplitude.h  GammaGamma2ffAmplitude.cc
 HwMEGammaGamma_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 5:0:1
 
 HwMEGammaHadron_la_SOURCES = \
 MEGammaP2Jets.cc MEGammaP2Jets.h
 HwMEGammaHadron_la_LDFLAGS = $(AM_LDFLAGS) -module -version-info 5:0:0
diff --git a/Tests/Makefile.am b/Tests/Makefile.am
--- a/Tests/Makefile.am
+++ b/Tests/Makefile.am
@@ -1,397 +1,398 @@
 AM_LDFLAGS += -module -avoid-version -rpath /dummy/path/not/used
 
 EXTRA_DIST = Inputs python Rivet
 
 EXTRA_LTLIBRARIES = LeptonTest.la GammaTest.la HadronTest.la DISTest.la
 
 if WANT_LIBFASTJET
 EXTRA_LTLIBRARIES += HadronJetTest.la LeptonJetTest.la
 HadronJetTest_la_SOURCES = \
 Hadron/VHTest.h Hadron/VHTest.cc\
 Hadron/VTest.h Hadron/VTest.cc\
 Hadron/HTest.h Hadron/HTest.cc
 HadronJetTest_la_CPPFLAGS = $(AM_CPPFLAGS) $(FASTJETINCLUDE) \
 -I$(FASTJETPATH)
 HadronJetTest_la_LIBADD = $(FASTJETLIBS)
 LeptonJetTest_la_SOURCES = \
 Lepton/TopDecay.h Lepton/TopDecay.cc
 LeptonJetTest_la_CPPFLAGS = $(AM_CPPFLAGS) $(FASTJETINCLUDE) \
 -I$(FASTJETPATH)
 LeptonJetTest_la_LIBADD = $(FASTJETLIBS)
 endif
 
 LeptonTest_la_SOURCES = \
 Lepton/VVTest.h Lepton/VVTest.cc \
 Lepton/VBFTest.h Lepton/VBFTest.cc \
 Lepton/VHTest.h Lepton/VHTest.cc \
 Lepton/FermionTest.h Lepton/FermionTest.cc
 
 GammaTest_la_SOURCES = \
 Gamma/GammaMETest.h  Gamma/GammaMETest.cc \
 Gamma/GammaPMETest.h Gamma/GammaPMETest.cc
 
 DISTest_la_SOURCES = \
 DIS/DISTest.h  DIS/DISTest.cc
 
 HadronTest_la_SOURCES = \
 Hadron/HadronVVTest.h  Hadron/HadronVVTest.cc\
 Hadron/HadronVBFTest.h  Hadron/HadronVBFTest.cc\
 Hadron/WHTest.h  Hadron/WHTest.cc\
 Hadron/ZHTest.h  Hadron/ZHTest.cc\
 Hadron/VGammaTest.h  Hadron/VGammaTest.cc\
 Hadron/ZJetTest.h  Hadron/ZJetTest.cc\
 Hadron/WJetTest.h  Hadron/WJetTest.cc\
 Hadron/QQHTest.h  Hadron/QQHTest.cc
 
 
 REPO = $(top_builddir)/src/HerwigDefaults.rpo
 HERWIG = $(top_builddir)/src/Herwig
 HWREAD = $(HERWIG) read --repo $(REPO) -L $(builddir)/.libs -i $(top_builddir)/src
 HWBUILD = $(HERWIG) build --repo $(REPO) -L $(builddir)/.libs -i $(top_builddir)/src
 HWINTEGRATE = $(HERWIG) integrate
 HWRUN = $(HERWIG) run -N $${NUMEVENTS:-10000}
 
 
 tests : tests-LEP tests-DIS tests-LHC tests-Gamma
 
 
 LEPDEPS = \
 test-LEP-VV \
 test-LEP-VH \
 test-LEP-VBF \
 test-LEP-BB \
 test-LEP-Quarks \
 test-LEP-Leptons
 
 if WANT_LIBFASTJET
 LEPDEPS += test-LEP-TopDecay
 endif
 
 tests-LEP : $(LEPDEPS)
 
 tests-DIS : test-DIS-Charged test-DIS-Neutral
 
 
 LHCDEPS = \
 test-LHC-WW test-LHC-WZ test-LHC-ZZ \
 test-LHC-ZGamma test-LHC-WGamma \
 test-LHC-ZH test-LHC-WH \
 test-LHC-ZJet test-LHC-WJet \
 test-LHC-Z test-LHC-W \
 test-LHC-ZZVBF test-LHC-VBF \
 test-LHC-WWVBF \
 test-LHC-bbH test-LHC-ttH \
 test-LHC-GammaGamma test-LHC-GammaJet \
 test-LHC-Higgs test-LHC-HiggsJet \
 test-LHC-QCDFast test-LHC-QCD \
 test-LHC-Top
 
 
 if WANT_LIBFASTJET
 LHCDEPS += \
 test-LHC-Bottom \
 test-LHC-WHJet test-LHC-ZHJet test-LHC-HJet \
 test-LHC-ZShower test-LHC-WShower \
 test-LHC-WHJet-Powheg test-LHC-ZHJet-Powheg test-LHC-HJet-Powheg \
 test-LHC-ZShower-Powheg test-LHC-WShower-Powheg
 endif
 
 tests-LHC : $(LHCDEPS)
 
 tests-Gamma : test-Gamma-FF test-Gamma-WW test-Gamma-P
 
 
 
 LEPLIBS = LeptonTest.la
 HADLIBS = HadronTest.la
 
 if WANT_LIBFASTJET
 LEPLIBS += LeptonJetTest.la
 HADLIBS += HadronJetTest.la
 endif
 
 
 test-LEP-% : Inputs/LEP-%.in $(LEPLIBS)
 	$(HWREAD) $<
 	$(HWRUN) $(notdir $(subst .in,.run,$<))
 
 test-Gamma-% : Inputs/Gamma-%.in GammaTest.la
 	$(HWREAD) $<
 	$(HWRUN) $(notdir $(subst .in,.run,$<))
 
 test-DIS-% : Inputs/DIS-%.in DISTest.la
 	$(HWREAD) $<
 	$(HWRUN) $(notdir $(subst .in,.run,$<))
 
 test-LHC-% : Inputs/LHC-%.in GammaTest.la $(HADLIBS)
 	$(HWREAD) $<
 	$(HWRUN) $(notdir $(subst .in,.run,$<))
 
 
 
 tests-Rivet : Rivet-EE Rivet-DIS Rivet-Fixed \
 	      Rivet-TVT-WZ Rivet-TVT-Photon Rivet-TVT-Jets \
 	      Rivet-LHC-Jets Rivet-LHC-EW Rivet-LHC-Photon Rivet-LHC-Higgs
 
 Rivet-%-UE-Cent.yoda : Rivet-%-UE-Cent.run Rivet-%-Cent.run
 	rm -rf $(subst .yoda,,$@)
 	mkdir $(subst .yoda,,$@)
 	mv $(subst .yoda,.run,$@) $(subst UE-,,$(subst .yoda,.run,$@)) $(subst .yoda,,$@)
 	cd $(subst .yoda,,$@); ../$(HWRUN) $(subst UE-,,$(subst .yoda,.run,$@)); mv $(subst UE-,,$@) ALICE_2015_PPCentrality.yoda
 	cd $(subst .yoda,,$@); export RIVET_ANALYSIS_PATH=`pwd`; ../$(HWRUN)  $(subst .yoda,.run,$@)
 	mv $(subst .yoda,,$@)/$@ .
 	rm -rf $(subst .yoda,,$@)
 
 Rivet-%.run : Rivet/%.in
 	$(HWBUILD) -c .cache/$(subst .run,,$@) $<
 
 Rivet-Matchbox-%.yoda : Rivet-Matchbox-%.run
 	$(HWINTEGRATE) -c .cache/$(subst .run,,$<) $<
 	$(HWRUN)       -c .cache/$(subst .run,,$<) $<
 
 Rivet-%.yoda : Rivet-%.run
 	$(HWRUN) $<
 
 Rivet/%.in :
 	python/make_input_files.py $(notdir $(subst .in,,$@))
 
 
 Rivet-inputfiles: $(shell echo Rivet/EE{,-Powheg,-Matchbox,-Dipole,-Dipole-MCatNLO,-Dipole-Matchbox-Powheg,-Matchbox-Powheg,-Merging}-{7.7,9.4,12,13,17,27.6,27.7,29,30.2,30.3,30.5,30.7,30.8,30,31.2,31.3,31.6,34,34.8,41,41.5,42.1,42.6,43.5,43.6,45,50,52,53.3,55,55.3,56,57,58,59.5,60.8,60,61.4,65.4,66,75.7,76,82,85,10,12.8,21.5,22,22.5,25,26.8,34.5,35,36.2,44,48.0,91,93.0,130,130.1,133,136,161,161.3,172,172.3,177,182.8,183,188.6,189,192,194.4,196,197,200,200.2,202,205,206,206.2,207,91-nopi}.in) \
 		  $(shell echo Rivet/EE-{183,189}-WW.in) \
                   $(shell echo Rivet/EE{,-Dipole,-Dipole-MCatNLO,-Dipole-Matchbox-Powheg,-Powheg,-Matchbox-Powheg}-{14,14.8}.in) \
 	          $(shell echo Rivet/EE{,-Dipole}-{10.5,11.96,12.8,13.96,16.86,21.84,26.8,28.48,35.44,48.0,97.0}-gg.in) \
                   $(shell echo Rivet/EE{,-Powheg,-Matchbox,-Dipole,-Dipole-MCatNLO,-Dipole-Matchbox-Powheg,-Matchbox-Powheg}-{2.2,2.6,3.0,3.2,4.17,4.3,4.41,5.0,5.2,4.6,4.8,5.8,6.2,6.5,6.6,7.0,7.4,3.63,4.03,4.5,8.8,9.27,9.46,9.51,10.52,10.52-sym,10.54,10.58,10.45,10.47,10.6}.in) \
                   $(shell echo Rivet/EE-{Upsilon,Upsilon2,Upsilon3,Upsilon4,Upsilon5,Upsilon4-asym,JPsi,Psi2S,Psi2S-All,Psi3770,Tau,Phi,Lambdac,Omega-Meson,Omega-Baryon,Eta,Xi0,Xic0,Xicp,Omegac0,Ds,Bc,Etac,Xim}.in) \
 	          $(shell echo Rivet/DIS{,-NoME,-Powheg,-Matchbox,-Dipole,-Dipole-MCatNLO,-Dipole-Matchbox-Powheg,-Matchbox-Powheg,-Merging}-{225,251,300,318,318-CMS}-e+-{VeryLow,Low,Med,High}Q2.in) \
 	          $(shell echo Rivet/DIS{,-NoME,-Powheg,-Matchbox,-Dipole,-Dipole-MCatNLO,-Dipole-Matchbox-Powheg,-Matchbox-Powheg,-Merging}-318-{e+,e-}-CC-{VeryLow,Low,Med,High}Q2.in) \
 		  $(shell echo Rivet/DIS{,-NoME,-Powheg,-Matchbox,-Dipole,-Dipole-MCatNLO,-Dipole-Matchbox-Powheg,-Matchbox-Powheg,-Merging}-{296,300,318}-e--{VeryLow,Low,Med,High}Q2.in) \
                   $(shell echo Rivet/TVT{,-Powheg,-Matchbox,-Dipole,-Dipole-MCatNLO,-Dipole-Matchbox-Powheg,-Matchbox-Powheg,-Merging}-{Run-I-Z,Run-I-W,Run-I-WZ,Run-II-Z-e,Run-II-Z-{,LowMass-,HighMass-}mu,Run-II-W}.in) \
 	          $(shell echo Rivet/TVT{,-Dipole}-Run-II-{DiPhoton-GammaGamma,DiPhoton-GammaJet,PromptPhoton}.in) \
 	          $(shell echo Rivet/TVT-Powheg-Run-II-{DiPhoton-GammaGamma,DiPhoton-GammaJet}.in) \
                   $(shell echo Rivet/TVT{,-Dipole,-Dipole-MCatNLO,-Dipole-Matchbox-Powheg,-Matchbox,-Matchbox-Powheg,-Merging}-Run-{I,II}-{Jets-{1..6},DiJets-{1..4}}.in ) \
 	          $(shell echo Rivet/TVT{,-Dipole,-Dipole-MCatNLO,-Dipole-Matchbox-Powheg,-Matchbox,-Matchbox-Powheg,-Merging}-{630-Jets-{1..3},300-Jets-1,900-Jets-1}.in ) \
                   $(shell echo Rivet/TVT{,-Dipole}-{Run-I,Run-II,300,630,900}-UE.in) \
                   $(shell echo Rivet/LHC{,-Dipole,-Dipole-MCatNLO,-Dipole-Matchbox-Powheg,-Matchbox,-Matchbox-Powheg,-Merging}-7-DiJets-{1..7}-{A,B,C}.in ) \
                   $(shell echo Rivet/LHC{,-Dipole,-Dipole-MCatNLO,-Dipole-Matchbox-Powheg,-Matchbox,-Matchbox-Powheg,-Merging}-13-DiJets-{{1..11}-A,{6..11}-B}.in ) \
                   $(shell echo Rivet/LHC{,-Dipole,-Dipole-MCatNLO,-Dipole-Matchbox-Powheg,-Matchbox,-Matchbox-Powheg,-Merging}-{7,8,13}-Jets-{0..10}.in ) \
 	          $(shell echo Rivet/LHC{,-Dipole}-{900,2360,2760,7,8,13}-UE.in ) \
 		  $(shell echo Rivet/LHC{,-Dipole}-2760-Jets-{1..3}.in ) \
 	          $(shell echo Rivet/LHC{,-Dipole}-{900,7,13}-UE-Long.in ) \
 		  $(shell echo Rivet/LHC{,-Dipole,-Dipole-MCatNLO,-Dipole-Matchbox-Powheg,-Matchbox,-Matchbox-Powheg,-Merging}-7-Charm-{0..5}.in) \
 		  $(shell echo Rivet/LHC{,-Dipole,-Dipole-MCatNLO,-Dipole-Matchbox-Powheg,-Matchbox,-Matchbox-Powheg,-Merging}-{5,13}-Charm-0.in) \
 		  $(shell echo Rivet/LHC{,-Dipole,-Dipole-MCatNLO,-Dipole-Matchbox-Powheg,-Matchbox,-Matchbox-Powheg,-Merging}-7-Bottom-{0..9}.in) \
 		  $(shell echo Rivet/LHC{,-Dipole,-Dipole-MCatNLO,-Dipole-Matchbox-Powheg,-Matchbox,-Matchbox-Powheg,-Merging}-13-Bottom-{0..6}.in) \
 		  $(shell echo Rivet/LHC{,-Dipole,-Dipole-MCatNLO,-Dipole-Matchbox-Powheg,-Matchbox,-Matchbox-Powheg,-Merging}-7-Top-{L,SL}.in) \
 		  $(shell echo Rivet/LHC{,-Dipole,-Dipole-MCatNLO,-Dipole-Matchbox-Powheg,-Matchbox,-Matchbox-Powheg,-Merging}-{8,13}-Top-{All,L,SL}.in) \
                   $(shell echo Rivet/Star{,-Dipole}-{UE,Jets-{1..4}}.in ) \
 	          $(shell echo Rivet/SppS{,-Dipole}-{53,63,200,500,546,900}-UE.in ) \
                   $(shell echo Rivet/LHC{,-Matchbox,-Matchbox-Powheg,-Powheg,-Dipole,-Dipole-MCatNLO,-Dipole-Matchbox-Powheg,-Merging}-{{,8-}W-{e,mu},13-W-mu,{,8-,13-}Z-{e,mu}-Mass{1..5},13-Z-nu,Z-mu-SOPHTY,WZ,WW-{emu,ll},13-WW-ll,13-ZZ-ll,ZZ-{ll,lv},{8,13}-WZ,8-ZZ-lv,8-WW-ll,Z-mu-Short}.in) \
                   $(shell echo Rivet/LHC{,-Dipole}-7-{W,Z}Gamma-{e,mu}.in) \
                   $(shell echo Rivet/LHC{,-Dipole}-8-ZGamma-{e,mu}.in) \
 	          $(shell echo Rivet/LHC{,-Matchbox,-Matchbox-Powheg,-Dipole,-Dipole-MCatNLO,-Dipole-Matchbox-Powheg,-Merging}-{7-W-Jet-{1..3}-e,7-Z-Jet-{0..3}-e,7-Z-Jet-0-mu}.in) \
 	          $(shell echo Rivet/LHC{-Matchbox,-Matchbox-Powheg,-Dipole-MCatNLO,-Dipole-Matchbox-Powheg,-Merging}-{Z-b,Z-bb,8-Z-b,8-Z-bb,13-Z-b,13-Z-bb,W-b,8-Z-jj}.in) \
 		  $(shell echo Rivet/LHC{,-Dipole}-{7,8,13}-PromptPhoton-{1..5}.in) Rivet/LHC-GammaGamma-7.in \
 	          $(shell echo Rivet/LHC{,-Powheg,-Dipole}-{7,8,13}-{DiPhoton-GammaGamma,DiPhoton-GammaJet}.in) \
 	          $(shell echo Rivet/LHC{,-Powheg,-Matchbox,-Matchbox-Powheg,-Dipole,-Dipole-MCatNLO,-Dipole-Matchbox-Powheg,-Merging}-{ggH,VBF,WH,ZH}.in) \
                   $(shell echo Rivet/LHC{,-Powheg,-Matchbox,-Matchbox-Powheg,-Dipole,-Dipole-MCatNLO,-Dipole-Matchbox-Powheg,-Merging}-8-{{ggH,VBF,WH,ZH}{,-GammaGamma},ggH-WW}.in) \
                   $(shell echo Rivet/LHC{,-Matchbox,-Matchbox-Powheg,-Dipole,-Dipole-MCatNLO,-Dipole-Matchbox-Powheg,-Merging}-ggHJet.in) \
                   $(shell echo Rivet/ISR{,-Dipole}-{{30,44,53,62}-UE,{44,62}-Z-mu}.in Rivet/EHS{,-Dipole}-UE.in) \
                   $(shell echo Rivet/SPS{,-Dipole}-{17.4-UE,200-Z-mu}.in ) \
                   $(shell echo Rivet/Fermilab{,-Dipole}-{27.4,38.8}-Z-mu.in )
 
 #$(shell echo Rivet/LHC{,-Dipole}-{7,13}{,-UE}-Cent.in )
 
-
 Rivet-GammaGamma: Rivet-GammaGamma/done
 	touch $@
 
 Rivet-GammaGamma/done: $(shell echo Rivet-GammaGamma-mumu-{3.5,4.5,5.5,6.5,7.5,9.0,12.5,17.5,30.0}.yoda )
 	rm -rf Rivet-GammaGamma
 	python/merge-GammaGamma GammaGamma
 	rivet-mkhtml -o Rivet-GammaGamma GammaGamma.yoda:Hw
 	touch $@
 
 Rivet-EE-Gamma: Rivet-EE-Gamma/done
 	touch $@
 
 Rivet-EE-Gamma/done: $(shell echo Rivet-EE-Gamma-Direct-mumu-{161,172,183,189,196,206}.yoda ) \
-                      $(shell echo Rivet-EE-Gamma-Direct-tautau-{189,196,206}.yoda ) \
-	              $(shell echo Rivet-EE-Gamma-{Direct,Single-Resolved,Double-Resolved}-Jets-{198,206}.yoda )
+                     $(shell echo Rivet-EE-Gamma-Direct-tautau-{189,196,206}.yoda ) \
+	             $(shell echo Rivet-EE-Gamma-{pi0,Eta,EtaPrime}-10.58.yoda ) \
+                     $(shell echo Rivet-EE-Gamma-{Eta-{1,29},EtaPrime-{34.3,91.2}}.yoda ) \
+	             $(shell echo Rivet-EE-Gamma-{Direct,Single-Resolved,Double-Resolved}-Jets-{198,206}.yoda )
 	rm -rf Rivet-EE-Gamma
 	python/merge-EE-Gamma EE-Gamma
 	rivet-mkhtml -o Rivet-EE-Gamma EE-Gamma.yoda:Hw
 	touch $@
 
 Rivet-EE : Rivet-EE/done
 	touch $@
 
 Rivet-EE/done : $(shell echo Rivet{,-Powheg}-EE-{7.7,9.4,12,13,14,14.8,17,27.6,27.7,29,30.2,30.3,30.5,30.7,30.8,30,31.2,31.3,31.6,34,34.8,43.5,43.6,45,50,52,53.3,55,55.3,56,57,58,59.5,60.8,60,61.4,65.4,66,75.7,76,10,12.8,21.5,22,22.5,25,26.8,34.5,35,36.2,41,41.5,42.1,42.6,44,48.0,82,85,91,93.0,130,130.1,133,136,136.1,161,161.3,172,172.3,177,182.8,183,188.6,189,192,194.4,196,197,200,200.2,202,205,206,206.2,207,91-nopi}.yoda) \
 		$(shell echo Rivet-EE-{183,189}-WW.yoda) \
 	  	$(shell echo Rivet-EE-{10.5,11.96,12.8,13.96,16.86,21.84,26.8,28.48,35.44,48.0,97.0}-gg.yoda) \
 	  	$(shell echo Rivet-EE-{10.52,10.52-sym,10.6,2.2,2.6,3.0,3.2,4.6,4.8,5.8,6.2,6.5,6.6,7.0,7.4,3.63,4.03,4.17,4.3,4.41,5.0,5.2,4.5,8.8,9.27,9.46,9.51,10.54,10.58,10.45,10.47,Upsilon,Upsilon2,Upsilon3,Upsilon4,Upsilon5,Upsilon4-asym,Tau,Phi,Lambdac,Omega-Meson,Omega-Baryon,Eta,Xi0,Xic0,Xicp,Omegac0,Ds,Bc,Etac,Xim,JPsi,Psi2S,Psi2S-All,Psi3770}.yoda)
 	rm -rf Rivet-EE
 	python/merge-EE --with-gg --with-decay --with-WW EE
 	python/merge-EE Powheg-EE
 	rivet-mkhtml -o Rivet-EE EE.yoda:Hw Powheg-EE.yoda:Hw-Powheg
 	python/plot-EE Rivet-EE
 	touch $@
 
 Rivet-LowEnergy-%.yoda:
 	$(HWBUILD) -c .cache/$(subst .yoda,,$@) Rivet/$(subst .yoda,.in,$@)
 	$(HWRUN)  $(subst .yoda,.run,$@)
 
 Rivet-LowEnergy-EE-%:
 	args="--process "$(word 1,$(subst -, ,$(subst Rivet-LowEnergy-EE-,,$@))); if [ -n "$(strip $(word 2,$(subst -, ,$(subst Rivet-LowEnergy-EE-,,$@))))" ]; then args+=" --flavour "$(word 2,$(subst -, ,$(subst Rivet-LowEnergy-EE-,,$@))); fi; OUTPUT=`python/LowEnergy-EE.py $$args --non-perturbative --perturbative`; $(MAKE) $$OUTPUT NUMEVENTS=$${NUMEVENTS:-10000};
 	args="--process "$(word 1,$(subst -, ,$(subst Rivet-LowEnergy-EE-,,$@))); plots=`python/LowEnergy-EE.py $$args --plots`; python/mergeLowEnergy.py $(subst Rivet-LowEnergy-,,$@) $$plots; if [ -e LowEnergy-NonPerturbative-EE-$(subst Rivet-LowEnergy-EE-,,$@).yoda ] && [ -e LowEnergy-Perturbative-EE-$(subst Rivet-LowEnergy-EE-,,$@).yoda ]; then rivet-mkhtml -o Rivet-LowEnergy-EE-$(subst Rivet-LowEnergy-EE-,,$@) LowEnergy-NonPerturbative-EE-$(subst Rivet-LowEnergy-EE-,,$@).yoda:"Non-Pert" LowEnergy-Perturbative-EE-$(subst Rivet-LowEnergy-EE-,,$@).yoda:"Pert" $$plots; elif [ -e LowEnergy-NonPerturbative-EE-$(subst Rivet-LowEnergy-EE-,,$@).yoda ]; then rivet-mkhtml -o Rivet-LowEnergy-EE-$(subst Rivet-LowEnergy-EE-,,$@) LowEnergy-NonPerturbative-EE-$(subst Rivet-LowEnergy-EE-,,$@).yoda:"Non-Pert" $$plots; elif [ -e  LowEnergy-Perturbative-EE-$(subst Rivet-LowEnergy-EE-,,$@).yoda ]; then  rivet-mkhtml -o Rivet-LowEnergy-EE-$(subst Rivet-LowEnergy-EE-,,$@)  LowEnergy-Perturbative-EE-$(subst Rivet-LowEnergy-EE-,,$@).yoda:"Pert" $$plots; fi
 
 Rivet-LowEnergy-Photon-%:
 	args="--process "$(word 1,$(subst -, ,$(subst Rivet-LowEnergy-Photon-,,$@))); OUTPUT=`python/LowEnergy-Photon.py $$args --non-perturbative`; $(MAKE) $$OUTPUT NUMEVENTS=$${NUMEVENTS:-10000};
 	args="--process "$(word 1,$(subst -, ,$(subst Rivet-LowEnergy-Photon-,,$@))); plots=`python/LowEnergy-Photon.py $$args --plots`; python/mergeLowEnergy.py $(subst Rivet-LowEnergy-Photon-,GammaGamma-,$@) $$plots; if [ -e LowEnergy-NonPerturbative-GammaGamma-$(subst Rivet-LowEnergy-Photon-,,$@).yoda ] && [ -e LowEnergy-Perturbative-GammaGamma-$(subst Rivet-LowEnergy-Photon-,,$@).yoda ]; then rivet-mkhtml -o Rivet-LowEnergy-Photon-$(subst Rivet-LowEnergy-Photon-,,$@) LowEnergy-NonPerturbative-GammaGamma-$(subst Rivet-LowEnergy-Photon-,,$@).yoda:"Non-Pert" LowEnergy-Perturbative-GammaGamma-$(subst Rivet-LowEnergy-Photon-,,$@).yoda:"Pert" $$plots; elif [ -e LowEnergy-NonPerturbative-GammaGamma-$(subst Rivet-LowEnergy-Photon-,,$@).yoda ]; then rivet-mkhtml -o Rivet-LowEnergy-Photon-$(subst Rivet-LowEnergy-Photon-,,$@) LowEnergy-NonPerturbative-GammaGamma-$(subst Rivet-LowEnergy-Photon-,,$@).yoda:"Non-Pert" $$plots; elif [ -e  LowEnergy-Perturbative-GammaGamma-$(subst Rivet-LowEnergy-Photon-,,$@).yoda ]; then  rivet-mkhtml -o Rivet-LowEnergy-Photon-$(subst Rivet-LowEnergy-Photon-,,$@)  LowEnergy-Perturbative-GammaGamma-$(subst Rivet-LowEnergy-Photon-,,$@).yoda:"Pert" $$plots; fi
 
 Rivet-R:
 	OUTPUT=`python/R.py --perturbative --non-perturbative`; $(MAKE) $$OUTPUT NUMEVENTS=$${NUMEVENTS:-10000};
 	plots=`python/R.py --perturbative --non-perturbative --plots`; python/mergeLowEnergy.py R $$plots; rivet-mkhtml -o Rivet-R LowEnergy-Perturbative-R.yoda:"Pert" LowEnergy-NonPerturbative-R.yoda:"Non-Pert" $$plots
 
 Rivet-DIS : Rivet-DIS/done
 	touch $@
 
 Rivet-DIS/done: $(shell echo Rivet{-DIS,-NoME-DIS,-Powheg-DIS}-{225,251,300,318,318-CMS}-e+-{VeryLow,Low,Med,High}Q2.yoda) \
 		$(shell echo Rivet{-DIS,-NoME-DIS,-Powheg-DIS}-{296,300,318}-e--{VeryLow,Low,Med,High}Q2.yoda) \
                 $(shell echo Rivet{-DIS,-NoME-DIS,-Powheg-DIS}-318-{e+,e-}-CC-{VeryLow,Low,Med,High}Q2.yoda)
 	rm -rf Rivet-DIS
 	python/merge-DIS DIS
 	python/merge-DIS Powheg-DIS
 	python/merge-DIS NoME-DIS
 	rivet-mkhtml -o Rivet-DIS DIS.yoda:Hw Powheg-DIS.yoda:Hw-Powheg NoME-DIS.yoda:Hw-NoME
 	touch $@
 
 Rivet-TVT-EW : Rivet-TVT-EW/done
 	touch $@
 
 Rivet-TVT-EW/done:  $(shell echo Rivet{,-Powheg}-TVT-{Run-I-Z,Run-I-W,Run-I-WZ,Run-II-Z-{e,{,LowMass-,HighMass-}mu},Run-II-W}.yoda)
 	rm -rf Rivet-TVT-EW
 	python/merge-TVT-EW TVT
 	python/merge-TVT-EW Powheg-TVT
 	rivet-mkhtml -o Rivet-TVT-EW TVT-EW.yoda:Hw Powheg-TVT-EW.yoda:Hw-Powheg
 	touch $@
 
 Rivet-TVT-Photon : Rivet-TVT-Photon/done
 	touch $@
 
 Rivet-TVT-Photon/done: $(shell echo Rivet{,-Powheg}-TVT-Run-II-{DiPhoton-GammaGamma,DiPhoton-GammaJet}.yoda Rivet-TVT-Run-II-PromptPhoton.yoda)
 	rm -rf Rivet-TVT-Photon
 	python/merge-TVT-Photon TVT
 	python/merge-TVT-Photon Powheg-TVT
 	rivet-mkhtml -o Rivet-TVT-Photon TVT-Photon.yoda:Hw Powheg-TVT-Photon.yoda:Hw-Powheg
 	touch $@
 
 
 
 Rivet-TVT-Jets : Rivet-TVT-Jets/done
 	touch $@
 
 Rivet-TVT-Jets/done: $(shell echo Rivet-TVT-Run-{I,II}-{Jets-{1..6},DiJets-{1..4}}.yoda ) \
 	             $(shell echo Rivet-TVT-{630-Jets-{1..3},300-Jets-1,900-Jets-1}.yoda ) \
                      $(shell echo Rivet-TVT-{Run-I,Run-II,300,630,900}-UE.yoda)
 	rm -rf Rivet-TVT-Jets
 	python/merge-TVT-Jets TVT
 	rivet-mkhtml -o Rivet-TVT-Jets TVT-Jets.yoda:Hw
 	touch $@
 
 Rivet-Fixed : Rivet-Fixed/done
 	touch $@
 
 
 Rivet-Fixed/done : $(shell echo Rivet-SppS-{53,63,200,500,546,900}-UE.yoda ) \
 	          $(shell echo Rivet-ISR-{{30,44,53,62}-UE,{44,62}-Z-mu}.yoda ) Rivet-EHS-UE.yoda \
                   $(shell echo Rivet-Star-{UE,Jets-{1..4}}.yoda ) \
                   $(shell echo Rivet-SPS-{17.4-UE,200-Z-mu}.yoda ) \
                   $(shell echo Rivet-Fermilab-{27.4,38.8}-Z-mu.yoda )
 	rm -rf Rivet-Fixed
 	python/merge-Fixed Fixed
 	rivet-mkhtml -o Rivet-Fixed Fixed.yoda:Hw
 	touch $@
 
 Rivet-LHC-Jets : Rivet-LHC-Jets/done
 	touch $@
 
 Rivet-LHC-Jets/done : \
 	        $(shell echo Rivet-LHC-7-DiJets-{1..7}-{A,B,C}.yoda   ) \
 	        $(shell echo Rivet-LHC-13-DiJets-{{1..11}-A,{6..11}-B}.yoda   ) \
 	        $(shell echo Rivet-LHC-{7,8,13}-Jets-{0..10}.yoda     ) \
 	        $(shell echo Rivet-LHC-2760-Jets-{1..3}.yoda     ) \
 	        $(shell echo Rivet-LHC-{900,2360,2760,7,8,13}-UE.yoda ) \
 	        $(shell echo Rivet-LHC-{900,7,13}-UE-Long.yoda        ) \
 		$(shell echo Rivet-LHC-7-Charm-{0..5}.yoda            ) \
 		$(shell echo Rivet-LHC-{5,13}-Charm-0.yoda            ) \
 		$(shell echo Rivet-LHC-7-Bottom-{0..9}.yoda           ) \
 		$(shell echo Rivet-LHC-13-Bottom-{0..6}.yoda           ) \
 		$(shell echo Rivet-LHC-{7,8,13}-Top-{L,SL}.yoda ) \
 		$(shell echo Rivet-LHC-{8,13}-Top-All.yoda )
 #	        $(shell echo Rivet-LHC-{7,13}-UE-Cent.yoda )
 	rm -rf Rivet-LHC-Jets
 	python/merge-LHC-Jets LHC
 	rivet-mkhtml -o Rivet-LHC-Jets LHC-Jets.yoda:Hw
 	touch $@
 
 
 Rivet-LHC-EW : Rivet-LHC-EW/done
 	touch $@
 
 Rivet-LHC-EW/done: \
 		$(shell echo Rivet{,-Powheg}-LHC-{{,8-}W-{e,mu},13-W-mu,{,8-,13-}Z-{e,mu}-Mass{1..5},13-Z-nu,Z-mu-SOPHTY,WZ,WW-{emu,ll},13-WW-ll,ZZ-{ll,lv},{8,13}-WZ,13-ZZ-ll,8-ZZ-lv,8-WW-ll,Z-mu-Short}.yoda) \
 		$(shell echo Rivet-LHC-{7-W-Jet-{1..3}-e,7-Z-Jet-{0..3}-e,7-Z-Jet-0-mu}.yoda) \
 		$(shell echo Rivet-LHC-7-{W,Z}Gamma-{e,mu}.yoda) \
 		$(shell echo Rivet-LHC-8-ZGamma-{e,mu}.yoda)
 	rm -rf Rivet-LHC-EW;
 	python/merge-LHC-EW LHC
 	python/merge-LHC-EW Powheg-LHC
 	rivet-mkhtml -o Rivet-LHC-EW LHC-EW.yoda:Hw Powheg-LHC-EW.yoda:Hw-Powheg \
                                      Rivet-LHC-Z-mu-SOPHTY.yoda:Hw Rivet-Powheg-LHC-Z-mu-SOPHTY.yoda:Hw-Powheg
 	touch $@
 
 
 
 
 Rivet-LHC-Photon : Rivet-LHC-Photon/done
 	touch $@
 
 Rivet-LHC-Photon/done: \
 		$(shell echo Rivet-LHC-{7,8,13}-PromptPhoton-{1..5}.yoda) \
 		Rivet-LHC-GammaGamma-7.yoda \
 	    $(shell echo Rivet{,-Powheg}-LHC-{7,8,13}-{DiPhoton-GammaGamma,DiPhoton-GammaJet}.yoda)
 	rm -rf Rivet-LHC-Photon
 	python/merge-LHC-Photon LHC
 	python/merge-LHC-Photon Powheg-LHC
 	rivet-mkhtml -o Rivet-LHC-Photon LHC-Photon.yoda:Hw Powheg-LHC-Photon.yoda:Hw-Powheg
 	touch $@
 
 
 
 
 Rivet-LHC-Higgs : Rivet-LHC-Higgs/done
 	touch $@
 
 Rivet-LHC-Higgs/done:  \
 		$(shell echo Rivet{,-Powheg}-LHC-{ggH,VBF,WH,ZH}.yoda) \
         $(shell echo Rivet{,-Powheg}-LHC-8-{{ggH,VBF,WH,ZH}{,-GammaGamma},ggH-WW}.yoda) \
         Rivet-LHC-ggHJet.yoda
 	rivet-merge Rivet-Powheg-LHC-8-{ggH{-GammaGamma,-WW,},{VBF,ZH,WH}{,-GammaGamma}}.yoda -o Powheg-LHC-Higgs.yoda
 	rivet-merge Rivet-LHC-8-{ggH{-GammaGamma,-WW,},{VBF,ZH,WH}{,-GammaGamma}}.yoda -o LHC-Higgs.yoda
 	rm -rf Rivet-LHC-Higgs
 	rivet-mkhtml -o Rivet-LHC-Higgs Powheg-LHC-Higgs.yoda:Hw-Powheg LHC-Higgs.yoda:Hw\
 	                Rivet-Powheg-LHC-ggH.yoda:gg-Powheg Rivet-LHC-ggH.yoda:gg Rivet-LHC-ggHJet.yoda:HJet \
                         Rivet-Powheg-LHC-VBF.yoda:VBF-Powheg Rivet-LHC-VBF.yoda:VBF Rivet-LHC-WH.yoda:WH Rivet-LHC-ZH.yoda:ZH \
                         Rivet-Powheg-LHC-WH.yoda:WH-Powheg Rivet-Powheg-LHC-ZH.yoda:ZH-Powheg
 	touch $@
 
 
 
 
 
 clean-local:
 	rm -f *.out *.log *.tex *.top *.run *.dump *.mult *.Bmult *.yoda Rivet/*.in anatohepmc.txt hepmctoana.txt
 	rm -rf Rivet-*
 
 distclean-local:
 	rm -rf .cache
diff --git a/Tests/Rivet/EE-Gamma/EE-Gamma-Eta-1.in b/Tests/Rivet/EE-Gamma/EE-Gamma-Eta-1.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/EE-Gamma/EE-Gamma-Eta-1.in
@@ -0,0 +1,15 @@
+# -*- ThePEG-repository -*-
+##################################################
+# LEP physics parameters (override defaults) 
+##################################################
+set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 1.
+set /Herwig/Generators/EventGenerator:EventHandler:Cuts:MHatMin 0.9
+set /Herwig/Generators/EventGenerator:EventHandler:StatLevel Full
+set /Herwig/Partons/EEExtractor:FlatSHatY 1
+set /Herwig/ACDCSampler:Ntry 100000
+set /Herwig/Generators/EventGenerator:EventHandler:CascadeHandler NULL
+##################################################
+# select the analyses 
+##################################################
+# KLOE eta
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 KLOE_2013_I1199266
diff --git a/Tests/Rivet/EE-Gamma/EE-Gamma-Eta-10.58.in b/Tests/Rivet/EE-Gamma/EE-Gamma-Eta-10.58.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/EE-Gamma/EE-Gamma-Eta-10.58.in
@@ -0,0 +1,17 @@
+# -*- ThePEG-repository -*-
+##################################################
+# LEP physics parameters (override defaults) 
+##################################################
+set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 10.58
+set /Herwig/Generators/EventGenerator:EventHandler:Cuts:MHatMin 0.9
+set /Herwig/Generators/EventGenerator:EventHandler:StatLevel Full
+set /Herwig/Partons/EEExtractor:FlatSHatY 1
+set /Herwig/ACDCSampler:Ntry 100000
+set /Herwig/Generators/EventGenerator:EventHandler:CascadeHandler NULL
+##################################################
+# select the analyses 
+##################################################
+# CLEO pi0, eta, eta'
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CLEOII_1997_I446031
+# BABAR eta eta'
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 BABAR_2011_I883525
diff --git a/Tests/Rivet/EE-Gamma/EE-Gamma-Eta-29.in b/Tests/Rivet/EE-Gamma/EE-Gamma-Eta-29.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/EE-Gamma/EE-Gamma-Eta-29.in
@@ -0,0 +1,15 @@
+# -*- ThePEG-repository -*-
+##################################################
+# LEP physics parameters (override defaults) 
+##################################################
+set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 29.
+set /Herwig/Generators/EventGenerator:EventHandler:Cuts:MHatMin 0.9
+set /Herwig/Generators/EventGenerator:EventHandler:StatLevel Full
+set /Herwig/Partons/EEExtractor:FlatSHatY 1
+set /Herwig/ACDCSampler:Ntry 100000
+set /Herwig/Generators/EventGenerator:EventHandler:CascadeHandler NULL
+##################################################
+# select the analyses 
+##################################################
+# TPC eta
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 TPC_1986_I217503
diff --git a/Tests/Rivet/EE-Gamma/EE-Gamma-EtaPrime-10.58.in b/Tests/Rivet/EE-Gamma/EE-Gamma-EtaPrime-10.58.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/EE-Gamma/EE-Gamma-EtaPrime-10.58.in
@@ -0,0 +1,19 @@
+# -*- ThePEG-repository -*-
+##################################################
+# LEP physics parameters (override defaults) 
+##################################################
+set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 10.58
+set /Herwig/Generators/EventGenerator:EventHandler:Cuts:MHatMin 0.9
+set /Herwig/Generators/EventGenerator:EventHandler:StatLevel Full
+set /Herwig/Partons/EEExtractor:FlatSHatY 1
+set /Herwig/ACDCSampler:Ntry 100000
+set /Herwig/Generators/EventGenerator:EventHandler:CascadeHandler NULL
+##################################################
+# select the analyses 
+##################################################
+# CLEO pi0, eta, eta'
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CLEOII_1997_I446031
+# BABAR eta eta'
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 BABAR_2011_I883525
+# BABAR eta' double diff
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 BABAR_2018_I1691222
diff --git a/Tests/Rivet/EE-Gamma/EE-Gamma-EtaPrime-34.3.in b/Tests/Rivet/EE-Gamma/EE-Gamma-EtaPrime-34.3.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/EE-Gamma/EE-Gamma-EtaPrime-34.3.in
@@ -0,0 +1,15 @@
+# -*- ThePEG-repository -*-
+##################################################
+# LEP physics parameters (override defaults) 
+##################################################
+set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 34.3
+set /Herwig/Generators/EventGenerator:EventHandler:Cuts:MHatMin 0.9
+set /Herwig/Generators/EventGenerator:EventHandler:StatLevel Full
+set /Herwig/Partons/EEExtractor:FlatSHatY 1
+set /Herwig/ACDCSampler:Ntry 100000
+set /Herwig/Generators/EventGenerator:EventHandler:CascadeHandler NULL
+##################################################
+# select the analyses 
+##################################################
+# JADE eta'
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 JADE_1982_I177090
diff --git a/Tests/Rivet/EE-Gamma/EE-Gamma-EtaPrime-91.2.in b/Tests/Rivet/EE-Gamma/EE-Gamma-EtaPrime-91.2.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/EE-Gamma/EE-Gamma-EtaPrime-91.2.in
@@ -0,0 +1,15 @@
+# -*- ThePEG-repository -*-
+##################################################
+# LEP physics parameters (override defaults) 
+##################################################
+set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 91.2
+set /Herwig/Generators/EventGenerator:EventHandler:Cuts:MHatMin 0.9
+set /Herwig/Generators/EventGenerator:EventHandler:StatLevel Full
+set /Herwig/Partons/EEExtractor:FlatSHatY 1
+set /Herwig/ACDCSampler:Ntry 100000
+set /Herwig/Generators/EventGenerator:EventHandler:CascadeHandler NULL
+##################################################
+# select the analyses 
+##################################################
+# L3 eta'
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 L3_1998_I447945
diff --git a/Tests/Rivet/EE-Gamma/EE-Gamma-pi0-10.58.in b/Tests/Rivet/EE-Gamma/EE-Gamma-pi0-10.58.in
new file mode 100644
--- /dev/null
+++ b/Tests/Rivet/EE-Gamma/EE-Gamma-pi0-10.58.in
@@ -0,0 +1,19 @@
+# -*- ThePEG-repository -*-
+##################################################
+# LEP physics parameters (override defaults) 
+##################################################
+set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy 10.58
+set /Herwig/Generators/EventGenerator:EventHandler:Cuts:MHatMin 0.9
+set /Herwig/Generators/EventGenerator:EventHandler:StatLevel Full
+set /Herwig/Partons/EEExtractor:FlatSHatY 1
+set /Herwig/ACDCSampler:Ntry 100000
+set /Herwig/Generators/EventGenerator:EventHandler:CascadeHandler NULL
+##################################################
+# select the analyses 
+##################################################
+# CLEO pi0, eta, eta'
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 CLEOII_1997_I446031
+# BELLE pi0
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 BELLE_2012_I1114749
+# BABAR pi0
+insert /Herwig/Analysis/RivetAnalysis:Analyses 0 BABAR_2009_I821653
diff --git a/Tests/python/HerwigInputs.py b/Tests/python/HerwigInputs.py
--- a/Tests/python/HerwigInputs.py
+++ b/Tests/python/HerwigInputs.py
@@ -1,263 +1,265 @@
 # select the template to load
 # collider
 KNOWN_COLLIDERS = [
     "EE-Gamma",
     "BFactory",
     "EE",
     "DIS",
     "TVT",
     "LHC-GammaGamma",
     "LHC",
     "ISR",
     "Fermilab",
     "SppS",
     "Star",
     "SPS",
     "GammaGamma",
 ]
 
 def identifyCollider(name) :
     """ Work out name of collider
     """
     collider = ""
     for cand_collider in KNOWN_COLLIDERS:
         if cand_collider in name:
             collider = cand_collider
             break
     del cand_collider
     if "EHS" in name : collider="SPS"
     assert collider
     have_hadronic_collider = collider in ["TVT","LHC","ISR","SppS","Star","SPS","Fermilab"]
     return (collider,have_hadronic_collider)
 
 class StringBuilder(object):
     """
     Avoid expensive string additions until the end
     by building up a list first.
 
     This helper class avoids rewriting all the += lower down
     to list operations.
     """
     def __init__(self, init = None):
         self.lines = [] if init is None else [init]
 
     def __iadd__(self, line):
         self.lines.append(line)
         return self
 
     def __str__(self):
         return '\n'.join(self.lines)
 
 def identifySimulation(name,collider,have_hadronic_collider) :
     """ Work out the type of simulation
 
     Identify the parton shower and source of the matrix elements
     """
     parameters = {
         'shower'  : '',
         'bscheme' : '',
     }
     simulation=""
     # istart determines how many name parts need to be skipped
     istart = 1
     # Dipole shower with Matchbox Powheg
     if "Dipole-Matchbox-Powheg" in name :
         istart = 4
         simulation="Matchbox"
         parameters["shower"]  = "read Matchbox/Powheg-DipoleShower.in\n"
 
         # Dipole shower with internal Powheg - Todo: Finish modifying template files.
         '''
         elif "Dipole-Powheg" in name :
         istart = 3
         simulation="Powheg"
         parameters["shower"]  = "set /Herwig/EventHandlers/EventHandler:CascadeHandler /Herwig/DipoleShower/DipoleShowerHandler\nread snippets/Dipole_AutoTunes_gss.in\n"
         '''
 
     # Dipole shower with MCatNLO
     elif "Dipole-MCatNLO" in name :
         istart = 3
         simulation="Matchbox"
         parameters["shower"]  = "read Matchbox/MCatNLO-DipoleShower.in\n"
 
     # Dipole shower with Matchbox LO
     elif "Dipole-Matchbox-LO" in name :
         istart = 4
         simulation="Matchbox"
         parameters["shower"]  = "read Matchbox/LO-DipoleShower.in\n"
 
     # Dipole shower with internal LO
     elif "Dipole" in name :
         istart = 2
         simulation=""
         parameters["shower"]  = "set /Herwig/EventHandlers/EventHandler:CascadeHandler /Herwig/DipoleShower/DipoleShowerHandler\nread snippets/Dipole_AutoTunes_gss.in\n"
 
     # AO shower with Matchbox Powheg
     elif "Matchbox-Powheg" in name :
         istart = 3
         simulation="Matchbox"
         parameters["shower"] = "read Matchbox/Powheg-DefaultShower.in\n"
 
     # AO shower with MCatNLO
     elif "Matchbox" in name :
         istart = 2
         simulation="Matchbox"
         parameters["shower"] = "read Matchbox/MCatNLO-DefaultShower.in\n"
 
     # AO shower with internal Powheg
     elif "Powheg" in name :
         istart = 2
         simulation="Powheg"
 
     # Dipole shower with merging
     elif "Merging" in name :
         istart = 2
         simulation="Merging"
         thefactory="MergingFactory"
 
     # Flavour settings for Matchbox
     if simulation=="Matchbox" :
         parameters["bscheme"] = "read Matchbox/FiveFlavourScheme.in\n"
 
         if "Dipole" in parameters["shower"] :
             parameters["bscheme"] += "read Matchbox/FiveFlavourNoBMassScheme.in\n"
 
         if collider not in ['DIS','EE'] :
             parameters["nlo"] = "read Matchbox/MadGraph-OpenLoops.in\n"
 
     # Flavour settings for dipole shower with internal ME
     if simulation=="" and "Dipole" in parameters["shower"] :
         parameters["bscheme"] = "read snippets/DipoleShowerFiveFlavours.in"
 
     # find the template
     if simulation=="" :
         if collider=="LHC-GammaGamma" :
             istart += 1
             templateName="Hadron-Gamma.in"
         elif have_hadronic_collider :
             templateName="Hadron.in"
         elif collider=="EE-Gamma" :
             istart+=1
             if("Direct" in name) :
                 templateName="EE-Gamma-Direct.in"
             elif("Single-Resolved" in name) :
                 templateName="EE-Gamma-Single-Resolved.in"
             elif("Double-Resolved" in name) :
                 templateName="EE-Gamma-Double-Resolved.in"
             else :
                 templateName="EE.in"
         elif collider=="GammaGamma" :
             templateName="GammaGamma.in"
         elif collider != "BFactory" :
             templateName= "%s.in" % collider
         else :
             templateName= "EE.in"
     else :
         if have_hadronic_collider :
             templateName= "Hadron-%s.in" % simulation
             if simulation == "Merging" :
                 if "Charm" in name or "Bottom" in name or "Top" in name :
                     templateName= "Hadron-Merging-Massive.in"
         elif collider != "BFactory" :
             templateName= "%s-%s.in" % (collider,simulation)
         else :
             templateName= "EE-%s.in" % simulation
     # work out the name of the parameter file
     parameterName="-".join(name.split("-")[istart:])
     del istart
     return (simulation,templateName,parameterName,parameters)
 
 def addLeptonPairCut(minmass,maxmass):
     return "set /Herwig/Cuts/LeptonPairMassCut:MinMass %s*GeV\nset /Herwig/Cuts/LeptonPairMassCut:MaxMass %s*GeV\n" %(minmass,maxmass)
 
 def setHardProcessWidthToZero(list1):
   res=""
   for i in list1:
     res+="set /Herwig/Particles/"+i+":HardProcessWidth 0.\n"
   return res
 
 def jet_kt_cut(ktmin,ktmax=-1.):
     output = "set /Herwig/Cuts/JetKtCut:MinKT {E}*GeV\n".format(E=ktmin)
     if ktmax>0 :
         output += "set /Herwig/Cuts/JetKtCut:MaxKT {E}*GeV\n".format(E=ktmax)
     return output
 
 def mhat_cut(mmin,mmax=-1):
     output = "set /Herwig/Cuts/Cuts:MHatMin {E}*GeV\n".format(E=mmin)
     if mmax>0. :
         output += "set /Herwig/Cuts/Cuts:MHatMax {E}*GeV\n".format(E=mmax)
     return output
 
 def mhat_minm_maxm(e1,e2,e3):
     return """\
 set /Herwig/Cuts/Cuts:MHatMin {e1}*GeV
 set /Herwig/Cuts/MassCut:MinM {e2}*GeV
 set /Herwig/Cuts/MassCut:MaxM {e3}*GeV
 """.format(**locals())
 
 def collider_lumi(energy):
     return "set /Herwig/Generators/EventGenerator:EventHandler:LuminosityFunction:Energy {E}*GeV\n".format(E=energy)
 
 def insert_ME(me,process=None,ifname='Process',subprocess="SubProcess"):
     result = "insert /Herwig/MatrixElements/{subprocess}:MatrixElements 0 /Herwig/MatrixElements/{me}\n".format(**locals())
     if process is not None:
-        result += "set /Herwig/MatrixElements/{me}:{ifname} {process}".format(**locals())
-
+        if me=="MEgg2ff" :
+            result += "set /Herwig/MatrixElements/gg2ffAmp:{ifname} {process}".format(**locals())
+        else :
+            result += "set /Herwig/MatrixElements/{me}:{ifname} {process}".format(**locals())
     return result
 
 def particlegroup(factory,name,*particles):
     directory="MatrixElements/Matchbox"
     if(factory!="Factory") : directory="Merging"
     result = ["do /Herwig/{dir}/{fact}:StartParticleGroup {n}".format(n=name,fact=factory,dir=directory)]
     for p in particles:
         result.append(
             "insert /Herwig/{dir}/{fact}:ParticleGroup 0 /Herwig/Particles/{p}".format(p=p,fact=factory,dir=directory)
         )
     result.append("do /Herwig/{dir}/{fact}:EndParticleGroup".format(fact=factory,dir=directory))
     return '\n'.join(result)
 
 didaddfirstjet=False
 def addFirstJet(ptcut,ptmax=""):
     global didaddfirstjet
     if(didaddfirstjet):
       logging.error("Can only add jetcut once.")
       sys.exit(1)
 
     res="set  /Herwig/Cuts/Cuts:JetFinder  /Herwig/Cuts/JetFinder\n"
     res+="insert  /Herwig/Cuts/Cuts:MultiCuts 0  /Herwig/Cuts/JetCuts\n"
     res+="insert  /Herwig/Cuts/JetCuts:JetRegions 0  /Herwig/Cuts/FirstJet\n"
     if(ptcut!=""):
         res+="set /Herwig/Cuts/FirstJet:PtMin %s*GeV\n" % ptcut
     if(ptmax!=""):
         res+="set /Herwig/Cuts/FirstJet:PtMax %s*GeV\n" % ptmax
     didaddfirstjet=True
     return res
 
 didaddsecondjet=False
 def addSecondJet(ptcut):
     global didaddsecondjet
     if(didaddsecondjet):
       logging.error("Can only add second jetcut once.")
       sys.exit(1)
     res="insert /Herwig/Cuts/JetCuts:JetRegions 0  /Herwig/Cuts/SecondJet\n"
     res+="set /Herwig/Cuts/SecondJet:PtMin "+ptcut+"*GeV\n"
     didaddsecondjet=True
     return res
 
 didaddjetpair=False
 def addJetPairCut(minmass,maxmass=""):
   global didaddjetpair
   if(didaddjetpair):
       logging.error("Can only add second jetcut once.")
       sys.exit(1)
   res="""\
 create ThePEG::JetPairRegion /Herwig/Cuts/JetPairMass JetCuts.so
 set /Herwig/Cuts/JetPairMass:FirstRegion /Herwig/Cuts/FirstJet
 set /Herwig/Cuts/JetPairMass:SecondRegion /Herwig/Cuts/SecondJet
 insert /Herwig/Cuts/JetCuts:JetPairRegions 0  /Herwig/Cuts/JetPairMass
 set /Herwig/Cuts/JetPairMass:MassMin {mm}*GeV
 """.format(mm=minmass)
   if maxmass != "" :
       res+= "set /Herwig/Cuts/JetPairMass:MassMax %s*GeV\n" %maxmass
   didaddjetpair=True
   return res
diff --git a/Tests/python/make_input_files.py.in b/Tests/python/make_input_files.py.in
--- a/Tests/python/make_input_files.py.in
+++ b/Tests/python/make_input_files.py.in
@@ -1,1587 +1,1636 @@
 #! @PYTHON@
 # -*- mode: python -*-
 from __future__ import print_function
 import logging,sys,os
 from string import Template
 from HerwigInputs import *
 import sys
 if sys.version_info[:3] < (2,4,0):
     print ("rivet scripts require Python version >= 2.4.0... exiting")
     sys.exit(1)
 
 if __name__ == "__main__":
     import logging
     from optparse import OptionParser, OptionGroup
     parser = OptionParser(usage="%prog name [...]")
 
 
 simulation=""
 
 numberOfAddedProcesses=0
 def addProcess(thefactory,theProcess,Oas,Oew,scale,mergedlegs,NLOprocesses):
     global numberOfAddedProcesses
     global simulation
     numberOfAddedProcesses+=1
     res ="set "+thefactory+":OrderInAlphaS "+Oas+"\n"
     res+="set "+thefactory+":OrderInAlphaEW "+Oew+"\n"
     res+="do "+thefactory+":Process "+theProcess+" "
     if ( mergedlegs != 0 ):
       if simulation!="Merging":
           print ("simulation is not Merging, trying to add merged legs.")
           sys.exit(1)
       res+="["
       for j in range(mergedlegs):
         res+=" j "
       res+="]"
     res+="\n"
     if (NLOprocesses!=0):
        if simulation!="Merging":
           print ("simulation is not Merging, trying to add NLOProcesses.")
           sys.exit(1)
        res+="set MergingFactory:NLOProcesses %s \n" % NLOprocesses
     if ( scale != "" ):
       res+="set "+thefactory+":ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/"+scale+"\n"
     return res
 
 addedBRReweighter=False
 def addBRReweighter():
   global addedBRReweighter
   if(addedBRReweighter):
     logging.error("Can only add BRReweighter once.")
     sys.exit(1)
   res="create Herwig::BranchingRatioReweighter /Herwig/Generators/BRReweighter\n"
   res+="insert /Herwig/Generators/EventGenerator:EventHandler:PostHadronizationHandlers 0 /Herwig/Generators/BRReweighter\n"
   addedBRReweighter=True
   return res
 
 selecteddecaymode=False
 def selectDecayMode(particle,decaymodes):
   global selecteddecaymode
   res="do /Herwig/Particles/"+particle+":SelectDecayModes"
   for decay in decaymodes:
     res+=" /Herwig/Particles/"+particle+"/"+decay
   res+="\n"
   selecteddecaymode=True
   return res
 
 ME_Upsilon = """\
 create Herwig::MEee2VectorMeson /Herwig/MatrixElements/MEUpsilon HwMELepton.so
 set /Herwig/MatrixElements/MEUpsilon:VectorMeson /Herwig/Particles/Upsilon(4S)
 set /Herwig/MatrixElements/MEUpsilon:Coupling 96.72794
 """ + insert_ME("MEUpsilon")
 
 (opts, args) = parser.parse_args()
 ## Check args
 if len(args) != 1:
     logging.error("Must specify at least input file")
     sys.exit(1)
 
 name = args[0]
 print (name)
 # work out name and type of the collider
 (collider,have_hadronic_collider) = identifyCollider(name)
 
 # workout the type of simulation
 (simulation,templateName,parameterName,parameters)=identifySimulation(name,collider,have_hadronic_collider)
 
 if simulation=="Merging" :
     thefactory="MergingFactory"
 else :
     thefactory="Factory"
         
 # settings for four flavour scheme
 fourFlavour="""
 read Matchbox/FourFlavourScheme.in
 {bjetgroup}
 set /Herwig/Cuts/MatchboxJetMatcher:Group bjet
 """.format(bjetgroup=particlegroup(thefactory,'bjet','b','bbar','c', 'cbar',
                                    's','sbar','d','dbar','u','ubar','g'))
 
 # work out the process and parameters
 process=StringBuilder()
 
 # DIS
 if(collider=="DIS") :
     if(simulation=="") :
         if "NoME" in name :
             process = StringBuilder("set /Herwig/Shower/ShowerHandler:HardEmission None")
             parameterName=parameterName.replace("NoME-","")
             parameterName=parameterName.replace("DIS-" ,"")
         if "CC" in parameterName :
             process += insert_ME("MEDISCC")
         else :
             process += insert_ME("MEDISNC")
     elif(simulation=="Powheg") :
         if "CC" in parameterName :
             process = StringBuilder(insert_ME("PowhegMEDISCC"))
         else :
             process = StringBuilder(insert_ME("PowhegMEDISNC"))
     elif(simulation=="Matchbox" ) :
         if "CC" in name :
             if "e-" in parameterName :
                 process = StringBuilder(addProcess(thefactory,"e- p -> nu_e j","0","2","",0,0))
             else :
                 process = StringBuilder(addProcess(thefactory,"e+ p -> nu_ebar j","0","2","",0,0))
         else :
             if "e-" in parameterName :
                 process = StringBuilder(addProcess(thefactory,"e- p -> e- j","0","2","",0,0))
             else :
                 process = StringBuilder(addProcess(thefactory,"e+ p -> e+ j","0","2","",0,0))
     elif(simulation=="Merging" ) :
         if "CC" in name :
             if "e-" in parameterName :
                 process = StringBuilder(addProcess(thefactory,"e- p -> e- j","0","2","",2,2))
             else :
                 process = StringBuilder(addProcess(thefactory,"e+ p -> e+ j","0","2","",2,2))
         else :
             if "e-" in parameterName :
                 process = StringBuilder(addProcess(thefactory,"e- p -> nu_e j","0","2","",2,2))
             else :
                 process = StringBuilder(addProcess(thefactory,"e+ p -> nu_ebar j","0","2","",2,2))
     Q2Min=1.
     Q2Max=1000000.
     if "VeryLow" in name :
         Q2Max=20.
         parameterName=parameterName.replace("-VeryLowQ2","")
     elif "Low" in name :
         Q2Min=20.
         Q2Max=100.
         parameterName=parameterName.replace("-LowQ2","")
     elif "Med" in name :
         Q2Min=100.
         Q2Max=1000.
         parameterName=parameterName.replace("-MedQ2","")
     elif "High" in name :
         Q2Min=1000.
         parameterName=parameterName.replace("-HighQ2","")
     if "CC" in name :
         process+="set /Herwig/Cuts/ChargedCurrentCut:MaxQ2 2%s\nset /Herwig/Cuts/ChargedCurrentCut:MinQ2 %s\n" %(Q2Max,Q2Min)
     else :
         process+="set /Herwig/Cuts/NeutralCurrentCut:MaxQ2 2%s\nset /Herwig/Cuts/NeutralCurrentCut:MinQ2 %s\n" %(Q2Max,Q2Min)
 # EE
 elif(collider=="EE") :
     if(simulation=="") :
         if "gg" in parameterName :
             process = StringBuilder("create Herwig::MEee2Higgs2SM /Herwig/MatrixElements/MEee2Higgs2SM\n")
             process+=insert_ME("MEee2Higgs2SM","Gluon","Allowed")
         elif "LL" in parameterName :
             process = StringBuilder(insert_ME("MEee2gZ2ll"))
             process += "set /Herwig/MatrixElements/MEee2gZ2ll:Allowed Charged\n"
         elif "WW" in parameterName : 
             process = StringBuilder(insert_ME("MEee2VV"))
             process += "set /Herwig/MatrixElements/MEee2VV:Process WW\n"
         else :
             process  = StringBuilder(insert_ME("MEee2gZ2qq"))
             try :
                 ecms = float(parameterName)
                 if(ecms<=3.75) :
                     process+= "set /Herwig/MatrixElements/MEee2gZ2qq:MaximumFlavour 3\n"
                 elif(ecms<=10.6) :
                     process+= "set /Herwig/MatrixElements/MEee2gZ2qq:MaximumFlavour 4\n"
             except :
                 pass
     elif(simulation=="Powheg") :
         if "LL" in parameterName :
             process = StringBuilder(insert_ME("PowhegMEee2gZ2ll"))
             process += "set /Herwig/MatrixElements/PowhegMEee2gZ2ll:Allowed Charged\n"
         else :
             process = StringBuilder(insert_ME("PowhegMEee2gZ2qq"))
             try :
                 ecms = float(parameterName)
                 if(ecms<=3.75) :
                     process+= "set /Herwig/MatrixElements/PowhegMEee2gZ2qq:MaximumFlavour 3\n"
                 elif(ecms<=10.6) :
                     process+= "set /Herwig/MatrixElements/PowhegMEee2gZ2qq:MaximumFlavour 4\n"
             except :
                 pass
     elif(simulation=="Matchbox" ) :
         try :
             ecms = float(parameterName)
             if(ecms<=3.75) :
                 process = StringBuilder(addProcess(thefactory,"e- e+ -> u ubar","0","2","",0,0))
                 process+=addProcess(thefactory,"e- e+ -> d dbar","0","2","",0,0)
                 process+=addProcess(thefactory,"e- e+ -> s sbar","0","2","",0,0)
             elif(ecms<=10.6) :
                 process = StringBuilder(addProcess(thefactory,"e- e+ -> u ubar","0","2","",0,0))
                 process+=addProcess(thefactory,"e- e+ -> d dbar","0","2","",0,0)
                 process+=addProcess(thefactory,"e- e+ -> c cbar","0","2","",0,0)
                 process+=addProcess(thefactory,"e- e+ -> s sbar","0","2","",0,0)
             else :
                 process = StringBuilder(addProcess(thefactory,"e- e+ -> j j","0","2","",0,0))
         except:
             process = StringBuilder(addProcess(thefactory,"e- e+ -> j j","0","2","",0,0))
     elif(simulation=="Merging" ) :
         try :
             ecms = float(parameterName)
             if(ecms<=10.1) :
                 process = StringBuilder(addProcess(thefactory,"e- e+ -> j j","0","2","",2,2))
                 process+="read Matchbox/FourFlavourScheme.in"
             else :
                 process = StringBuilder(addProcess(thefactory,"e- e+ -> j j","0","2","",2,2))
         except:
             process = StringBuilder(addProcess(thefactory,"e- e+ -> j j","0","2","",2,2))
 # EE-Gamma
 elif(collider=="EE-Gamma") :
     if(simulation=="") :
         if("mumu" in parameterName) :
             process = StringBuilder(insert_ME("MEgg2ff","Muon"))
             process +="set /Herwig/Cuts/Cuts:MHatMin 3.\n"
         elif( "tautau" in parameterName) :
             process = StringBuilder(insert_ME("MEgg2ff","Tau"))
             process +="set /Herwig/Cuts/Cuts:MHatMin 3.\n"
         elif( "Jets" in parameterName) :
             if("Direct" in parameterName ) :
                 process = StringBuilder(insert_ME("MEgg2ff","Quarks"))
             elif("Single-Resolved" in parameterName ) :
                 process = StringBuilder(insert_ME("MEGammaP2Jets",None,"Process","SubProcess"))
                 process+= insert_ME("MEGammaP2Jets",None,"Process","SubProcess2")
             else :
                 process = StringBuilder(insert_ME("MEQCD2to2"))
             process+="insert /Herwig/Cuts/Cuts:OneCuts[0] /Herwig/Cuts/JetKtCut"
             process+="set  /Herwig/Cuts/JetKtCut:MinKT 3."
+        elif ("pi0"  in parameterName or "Eta" in parameterName or "EtaPrime" in parameterName or
+              "EtaC" in parameterName):
+            if "EtaC" in parameterName :
+                mename="EtaC1S"
+            elif "pi0" in parameterName :
+                mename="pi0"
+            elif "EtaPrime" in parameterName :
+                mename="etaPrime"
+            elif "Eta" in parameterName :
+                mename="eta"
+            process = StringBuilder(insert_ME("MEff2ff%s" % mename) )
+            if "10.58" in parameterName: 
+                process+="cp /Herwig/MatrixElements/MEff2ff%s /Herwig/MatrixElements/MEff2ff%s2" % (mename,mename)
+                process+= insert_ME("MEff2ff%s2" % mename)
+                process+="cp /Herwig/MatrixElements/MEff2ff%s /Herwig/MatrixElements/MEff2ff%s3" % (mename,mename)
+                process+= insert_ME("MEff2ff%s3" % mename)
+                process+="set /Herwig/MatrixElements/MEff2ff%s:Q2_1Min 0.  " % mename
+                process+="set /Herwig/MatrixElements/MEff2ff%s:Q2_1Max 1.  " % mename
+                process+="set /Herwig/MatrixElements/MEff2ff%s:Q2_2Min 1.  " % mename
+                process+="set /Herwig/MatrixElements/MEff2ff%s:Q2_2Max 1e10" % mename
+                process+="set /Herwig/MatrixElements/MEff2ff%s2:Q2_2Min 0.  " % mename
+                process+="set /Herwig/MatrixElements/MEff2ff%s2:Q2_2Max 1.  " % mename
+                process+="set /Herwig/MatrixElements/MEff2ff%s2:Q2_1Min 1.  " % mename
+                process+="set /Herwig/MatrixElements/MEff2ff%s2:Q2_1Max 1e10" % mename
+                process+="set /Herwig/MatrixElements/MEff2ff%s3:Q2_2Min 1.  " % mename
+                process+="set /Herwig/MatrixElements/MEff2ff%s3:Q2_2Max 1e10" % mename
+                process+="set /Herwig/MatrixElements/MEff2ff%s3:Q2_1Min 1.  " % mename
+                process+="set /Herwig/MatrixElements/MEff2ff%s3:Q2_1Max 1e10" % mename
+        elif "ChiC0_2P" in parameterName :
+            process = StringBuilder(insert_ME("MEff2ffChiC02P"))
+        elif "ChiC2_2P" in parameterName :
+            process = StringBuilder(insert_ME("MEff2ffChiC22P"))
+        elif "ChiC2" in parameterName :
+            process = StringBuilder(insert_ME("MEff2ffChiC21P"))
+        elif "Onium" in parameterName :
+            process = StringBuilder(insert_ME("MEff2ffEtaC1S") )
+            process+= insert_ME("MEff2ffEtaC2S" )
+            process+= insert_ME("MEff2ffChiC01P")
+            process+= insert_ME("MEff2ffChiC21P")
+            process+= insert_ME("MEff2ffChiC22P")
+            process+= insert_ME("MEff2ffEtaB1S" )
+            process+= insert_ME("MEff2ffEtaB2S" )
+            process+= insert_ME("MEff2ffChiB01P")
+            process+= insert_ME("MEff2ffChiB21P")
+            process+= insert_ME("MEff2ffChiB02P")
+            process+= insert_ME("MEff2ffChiB22P")
+            process+= insert_ME("MEff2ffChiB03P")
+            process+= insert_ME("MEff2ffChiB23P")
+            process+= insert_ME("MEff2ffEtaB21D")
         else :
             print ("process not supported for Gamma Gamma processes at EE")
             quit()
     else :
         print ("Only internal matrix elements currently supported for Gamma Gamma processes at EE")
         quit()
 elif(collider=="GammaGamma") :
     if(simulation=="") :
         if("mumu" in parameterName) :
             process = StringBuilder(insert_ME("MEgg2ff"))
-            process +="set /Herwig/MatrixElements/MEgg2ff:Process Muon\n"
+            process +="set /Herwig/MatrixElements/gg2ffAmp:Process Muon\n"
             process +="set /Herwig/Cuts/Cuts:MHatMin 3.\n"
         else :
             print ("process not supported for Gamma Gamma processes at EE")
             quit()
     else :
         print ("Only internal matrix elements currently supported for Gamma Gamma processes at EE")
         quit()
 # TVT
 elif(collider=="TVT") :
     process = StringBuilder("set /Herwig/Generators/EventGenerator:EventHandler:BeamB /Herwig/Particles/pbar-\n")
     ecms=1960.
     if "Run-II" in parameterName :  ecms = 1960.0
     elif "Run-I" in parameterName : ecms = 1800.0
     elif "900" in parameterName :   ecms = 900.0
     elif "630" in parameterName :   ecms = 630.0
     elif "300" in parameterName :   ecms = 300.0
     process+=collider_lumi(ecms)
     if(simulation=="") :
         if "PromptPhoton" in parameterName :
             process+=insert_ME("MEGammaJet")
             process+="set /Herwig/Cuts/PhotonKtCut:MinKT 15.\n"
         elif "DiPhoton-GammaGamma" in parameterName :
             process+=insert_ME("MEGammaGamma")
             process+="set /Herwig/Cuts/PhotonKtCut:MinKT 5.\n"
             parameterName=parameterName.replace("-GammaGamma","")
         elif "DiPhoton-GammaJet" in parameterName :
             process+=insert_ME("MEGammaJet")
             process+="set /Herwig/Cuts/PhotonKtCut:MinKT 5.\n"
             parameterName=parameterName.replace("-GammaJet","")
         elif "UE" in parameterName :
             if "Dipole" in parameters["shower"]:
                 process+="read snippets/MB-DipoleShower.in\n"
             else:
                 process+="read snippets/MB.in\n"
             process+="read snippets/Diffraction.in\n"
                 
             process += "set /Herwig/Decays/DecayHandler:LifeTimeOption 0\n"
             process += "set /Herwig/Decays/DecayHandler:MaxLifeTime 10*mm\n"
         elif "Jets" in parameterName :
             process+=insert_ME("MEQCD2to2")
             process+="set /Herwig/UnderlyingEvent/MPIHandler:IdenticalToUE 0\n"
             if "DiJets" in name :
                 process +=jet_kt_cut( 30.)
                 cuts=[100.,300.,600.,900.,ecms]
                 for i in range(1,len(cuts)) :
                     tstring = "-DiJets-%s"%i
                     if tstring in parameterName :
                         process+=mhat_cut(cuts[i-1],cuts[i])
                         parameterName=parameterName.replace(tstring,"-DiJets")
             else :
                 if "Run" in parameterName :
                     cuts=[5.,20.,40.,80.,160.,320.]
                 elif "300" in parameterName :
                     cuts=[5.,]
                 elif "630" in parameterName :
                     cuts=[5.,20.,40.]
                 elif "900" in parameterName :
                     cuts=[5.,]
                 cuts.append(ecms)
                 for i in range(1,len(cuts)) :
                     tstring = "-Jets-%s"%i
                     if tstring in parameterName :
                         process+=jet_kt_cut(cuts[i-1],cuts[i])
                         parameterName=parameterName.replace(tstring,"-Jets")
         elif "Run-I-WZ" in parameterName :
             process+=insert_ME("MEqq2W2ff","Electron")
             process+=insert_ME("MEqq2gZ2ff","Electron")
         elif "Run-II-W" in parameterName or "Run-I-W" in parameterName :
             process+=insert_ME("MEqq2W2ff","Electron")
         elif "Run-II-Z-e" in parameterName or "Run-I-Z" in parameterName :
             process +=insert_ME("MEqq2gZ2ff","Electron")
         elif "Run-II-Z-LowMass-mu" in parameterName :
             process +=insert_ME("MEqq2gZ2ff","Muon")
             process+=addLeptonPairCut("25","70")
         elif "Run-II-Z-HighMass-mu" in parameterName :
             process +=insert_ME("MEqq2gZ2ff","Muon")
             process+=addLeptonPairCut("150","600")
         elif "Run-II-Z-mu" in parameterName :
             process +=insert_ME("MEqq2gZ2ff","Muon")
     elif(simulation=="Powheg") :
         if "Run-I-WZ" in parameterName :
             process+=insert_ME("PowhegMEqq2W2ff","Electron")
             process+=insert_ME("PowhegMEqq2gZ2ff","Electron")
         elif "Run-II-W" in parameterName or "Run-I-W" in parameterName :
             process+=insert_ME("PowhegMEqq2W2ff","Electron")
         elif "Run-II-Z-e" in parameterName or "Run-I-Z" in parameterName :
             process+=insert_ME("PowhegMEqq2gZ2ff","Electron")
         elif "Run-II-Z-LowMass-mu" in parameterName :
             process+=insert_ME("PowhegMEqq2gZ2ff","Muon")
             process+=addLeptonPairCut("25","70")
         elif "Run-II-Z-HighMass-mu" in parameterName :
             process+=insert_ME("PowhegMEqq2gZ2ff","Muon")
             process+=addLeptonPairCut("150","600")
         elif "Run-II-Z-mu" in parameterName :
             process+=insert_ME("PowhegMEqq2gZ2ff","Muon")
         elif "DiPhoton-GammaGamma" in parameterName :
             process+=insert_ME("MEGammaGammaPowheg","GammaGamma")
             process+=insert_ME("MEGammaGamma","gg")
             process+="set /Herwig/Cuts/PhotonKtCut:MinKT 5.\n"
             process+=jet_kt_cut(5.)
             parameterName=parameterName.replace("-GammaGamma","")
         elif "DiPhoton-GammaJet" in parameterName :
             process+=insert_ME("MEGammaGammaPowheg","VJet")
             process+="set /Herwig/Cuts/PhotonKtCut:MinKT 5.\n"
             process+=jet_kt_cut(5.)
             parameterName=parameterName.replace("-GammaJet","")
     elif(simulation=="Matchbox" or simulation=="Merging" ) :
         if "Jets" in parameterName :
             if(simulation=="Matchbox"):
                 process+=addProcess(thefactory,"p p -> j j","2","0","MaxJetPtScale",0,0)
             elif(simulation=="Merging"):
                 process+=addProcess(thefactory,"p p -> j j","2","0","MaxJetPtScale",1,0)
             if "DiJets" in parameterName :
                 process+=addFirstJet("30")+addSecondJet("25")
                 cuts=[100.,300.,600.,900.,ecms]
                 for i in range(1,len(cuts)) :
                     tstring = "-DiJets-%s"%i
                     if tstring in parameterName :
                         process+=addJetPairCut(cuts[i-1],cuts[i])
                         parameterName=parameterName.replace(tstring,"-DiJets")
             else :
                 if "Run" in parameterName :
                     cuts=[5.,20.,40.,80.,160.,320.]
                 elif "300" in parameterName :
                     cuts=[5.,]
                 elif "630" in parameterName :
                     cuts=[5.,20.,40.]
                 elif "900" in parameterName :
                     cuts=[5.,]
                 cuts.append(ecms)
                 for i in range(1,len(cuts)) :
                     tstring = "-Jets-%s"%i
                     if tstring in parameterName :
                         process+=addFirstJet(cuts[i-1],cuts[i])
                         parameterName=parameterName.replace(tstring,"-Jets")
         elif "Run-I-WZ" in parameterName :
             if(simulation=="Matchbox"):
                 process+=addProcess(thefactory,"p pbar e+ e-","0","2","LeptonPairMassScale",0,0)
                 process+=addProcess(thefactory,"p pbar e+ nu","0","2","LeptonPairMassScale",0,0)
                 process+=addProcess(thefactory,"p pbar e- nu","0","2","LeptonPairMassScale",0,0)
             elif(simulation=="Merging"):
                 process+=particlegroup(thefactory,'epm','e+','e-')
                 process+=particlegroup(thefactory,'epmnu','e+','e-','nu_e','nu_ebar')
                 process+=addProcess(thefactory,"p pbar epm epmnu","0","2","LeptonPairMassScale",2,2)
             process+=addLeptonPairCut("60","120")
         elif "Run-II-W" in parameterName or "Run-I-W" in parameterName :
             if(simulation=="Matchbox"):
                 process+=addProcess(thefactory,"p pbar e+ nu","0","2","LeptonPairMassScale",0,0)
                 process+=addProcess(thefactory,"p pbar e- nu","0","2","LeptonPairMassScale",0,0)
             elif(simulation=="Merging"):
                 process+=particlegroup(thefactory,'epm','e+','e-')
                 process+=addProcess(thefactory,"p pbar epm nu","0","2","LeptonPairMassScale",2,2)
             process+=addLeptonPairCut("60","120")
         elif "Run-II-Z-e" in parameterName or "Run-I-Z" in parameterName :
             if(simulation=="Matchbox"):
                 process+=addProcess(thefactory,"p pbar e+ e-","0","2","LeptonPairMassScale",0,0)
             elif(simulation=="Merging"):
                 process+=addProcess(thefactory,"p pbar e+ e-","0","2","LeptonPairMassScale",2,2)
             process+=addLeptonPairCut("60","120")
         elif "Run-II-Z-LowMass-mu" in parameterName :
             if(simulation=="Matchbox"):
                 process+=addProcess(thefactory,"p pbar mu+ mu-","0","2","LeptonPairMassScale",0,0)
             elif(simulation=="Merging"):
                 process+=addProcess(thefactory,"p pbar mu+ mu-","0","2","LeptonPairMassScale",2,2)
             process+=addLeptonPairCut("25","70")
         elif "Run-II-Z-HighMass-mu" in parameterName :
             if(simulation=="Matchbox"):
                 process+=addProcess(thefactory,"p pbar mu+ mu-","0","2","LeptonPairMassScale",0,0)
             elif(simulation=="Merging"):
                 process+=addProcess(thefactory,"p pbar mu+ mu-","0","2","LeptonPairMassScale",2,2)
             process+=addLeptonPairCut("150","600")
         elif "Run-II-Z-mu" in parameterName :
             if(simulation=="Matchbox"):
                 process+=addProcess(thefactory,"p pbar mu+ mu-","0","2","LeptonPairMassScale",0,0)
             elif(simulation=="Merging"):
                 process+=addProcess(thefactory,"p pbar mu+ mu-","0","2","LeptonPairMassScale",2,2)
             process+=addLeptonPairCut("60","120")
 # Star
 elif(collider=="Star" ) :
     process = StringBuilder("set /Herwig/Decays/DecayHandler:LifeTimeOption 0\n")
     process+= "set /Herwig/Decays/DecayHandler:MaxLifeTime 10*mm\n"
     process+= "set /Herwig/Generators/EventGenerator:EventHandler:BeamB /Herwig/Particles/p+\n"
     process+= collider_lumi(200.0)
     process+= "set /Herwig/Cuts/Cuts:X2Min 0.01\n"
     if(simulation=="") :
         if "UE" in parameterName :
             if "Dipole" in parameters["shower"]:
                 process+="read snippets/MB-DipoleShower.in\n"
             else:
                 process+="read snippets/MB.in\n"    
             process+="read snippets/Diffraction.in\n"
             
             
         else :
             process+=insert_ME("MEQCD2to2")
             process+="set /Herwig/UnderlyingEvent/MPIHandler:IdenticalToUE 0\n"
             if "Jets-1" in parameterName :   process+=jet_kt_cut(2.)
             elif "Jets-2" in parameterName : process+=jet_kt_cut(5.)
             elif "Jets-3" in parameterName : process+=jet_kt_cut(20.)
             elif "Jets-4" in parameterName : process+=jet_kt_cut(25.)
     else :
         logging.error("Star not supported for %s " % simulation)
         sys.exit(1)
 # ISR and SppS
 elif ( collider=="ISR" or collider =="SppS" or collider == "SPS" or collider == "Fermilab" ) :
     process = StringBuilder("set /Herwig/Decays/DecayHandler:LifeTimeOption 0\n")
     process+="set /Herwig/Decays/DecayHandler:MaxLifeTime 10*mm\n"
     if(collider=="SppS") :
         process = StringBuilder("set /Herwig/Generators/EventGenerator:EventHandler:BeamB /Herwig/Particles/pbar-\n")
     if    "17.4" in parameterName : process+=collider_lumi( 17.4)
     elif  "27.4" in parameterName : process+=collider_lumi( 27.4)
     elif  "30"   in parameterName : process+=collider_lumi( 30.4)
     elif  "38.8" in parameterName : process+=collider_lumi( 38.8)
     elif  "44"   in parameterName : process+=collider_lumi( 44.4)
     elif  "53"   in parameterName : process+=collider_lumi( 53.0)
     elif  "62"   in parameterName : process+=collider_lumi( 62.2)
     elif  "63"   in parameterName : process+=collider_lumi( 63.0)
     elif "200"   in parameterName : process+=collider_lumi(200.0)
     elif "500"   in parameterName : process+=collider_lumi(500.0)
     elif "546"   in parameterName : process+=collider_lumi(546.0)
     elif "900"   in parameterName : process+=collider_lumi(900.0)
     if "UE" in parameterName :
         if(simulation=="") :
             if "Dipole" in parameters["shower"]:
                 process+="read snippets/MB-DipoleShower.in\n"
             else:
                 process+="read snippets/MB.in\n"
                 process+="read snippets/Diffraction.in\n"
         else :
             logging.error(" SppS and ISR not supported for %s " % simulation)
             sys.exit(1)
     elif "Z-mu" in parameterName :
         if simulation == "" :
             process+=insert_ME("MEqq2gZ2ff","Muon")
             process+=mhat_minm_maxm(2,2,20)
         elif simulation == "Powheg" :
             process+=insert_ME("PowhegMEqq2gZ2ff","Muon")
             process+=mhat_minm_maxm(2,2,20)
         elif(simulation=="Matchbox"):
             process+=addProcess(thefactory,"p p mu+ mu-","0","2","LeptonPairMassScale",0,0)
             process+=addLeptonPairCut("2","20")
         elif(simulation=="Merging"):
             process+=addProcess(thefactory,"p p mu+ mu-","0","2","LeptonPairMassScale",2,2)
             process+=addLeptonPairCut("2","20")
         else :
             logging.error(" SppS and ISR not supported for %s " % simulation)
             sys.exit(1)
     else :
         logging.error(" Process not supported for SppS and ISR %s " % parameterName )
         sys.exit(1)
         
 # LHC
 elif(collider=="LHC") :
     ecms=7000.0
     if   parameterName.startswith("7-")   : ecms = 7000.0
     elif parameterName.startswith("8-")   : ecms = 8000.0
     elif parameterName.startswith("13-")  : ecms = 13000.0
     elif parameterName.startswith("900")  : ecms = 900.0
     elif parameterName.startswith("2360") : ecms = 2360.0
     elif parameterName.startswith("2760") : ecms = 2760.0
     elif parameterName.startswith("5-")   : ecms = 5000.0
     else                                  : ecms = 7000.0
     process = StringBuilder(collider_lumi(ecms))
     if(simulation=="") :
         if "VBF" in parameterName :
             process+=insert_ME("MEPP2HiggsVBF")
             if "GammaGamma" in parameterName :
                process+=selectDecayMode("h0",["h0->gamma,gamma;"])
                addedBRReweighter = True
             elif "WW" in parameterName :
                process+=selectDecayMode("h0",["h0->W+,W-;"])
                addedBRReweighter = True
             elif "ZZ" in parameterName :
                process+=selectDecayMode("h0",["h0->Z0,Z0;"])
                addedBRReweighter = True
             elif "8-" not in parameterName :
                 process+=selectDecayMode("h0",["h0->tau-,tau+;"])
                 addedBRReweighter = True
                 process+="set /Herwig/Particles/tau-:Stable Stable\n"
                 
         elif "ggHJet" in parameterName :
             process+=selectDecayMode("h0",["h0->tau-,tau+;"])
             addedBRReweighter = True
             process+="set /Herwig/Particles/tau-:Stable Stable\n"
             process+=insert_ME("MEHiggsJet")
             process+=jet_kt_cut(20.)
         elif "ggH" in parameterName :
             process+=insert_ME("MEHiggs")
             process+=insert_ME("MEHiggsJet","qqbar")
             process+=jet_kt_cut(0.0)
             if "GammaGamma" in parameterName :
                process+=selectDecayMode("h0",["h0->gamma,gamma;"])
                addedBRReweighter = True
             elif "WW" in parameterName :
                process+=selectDecayMode("h0",["h0->W+,W-;"])
                addedBRReweighter = True
             elif "ZZ" in parameterName :
                process+=selectDecayMode("h0",["h0->Z0,Z0;"])
                addedBRReweighter = True
             elif "8-" not in parameterName :
                 process+=selectDecayMode("h0",["h0->tau-,tau+;"])
                 addedBRReweighter = True
                 process+="set /Herwig/Particles/tau-:Stable Stable\n"
                 
         elif "PromptPhoton" in parameterName :
             process+=insert_ME("MEGammaJet")
             if "PromptPhoton-1" in parameterName :
                 process+="set /Herwig/Cuts/PhotonKtCut:MinKT 5.\n"
                 process+="set /Herwig/Cuts/PhotonKtCut:MaxKT 25.\n"
                 parameterName=parameterName.replace("-1","")
             elif "PromptPhoton-2" in parameterName :
                 process+="set /Herwig/Cuts/PhotonKtCut:MinKT 25.\n"
                 process+="set /Herwig/Cuts/PhotonKtCut:MaxKT 80.\n"
                 parameterName=parameterName.replace("-2","")
             elif "PromptPhoton-3" in parameterName :
                 process+="set /Herwig/Cuts/PhotonKtCut:MinKT 80.\n"
                 process+="set /Herwig/Cuts/PhotonKtCut:MaxKT 150.\n"
                 parameterName=parameterName.replace("-3","")
             elif "PromptPhoton-4" in parameterName :
                 process+="set /Herwig/Cuts/PhotonKtCut:MinKT 150.\n"
                 process+="set /Herwig/Cuts/PhotonKtCut:MaxKT 500.\n"
                 parameterName=parameterName.replace("-4","")
             elif "PromptPhoton-5" in parameterName :
                 process+="set /Herwig/Cuts/PhotonKtCut:MinKT 500.\n"
                 parameterName=parameterName.replace("-5","")
         elif "DiPhoton-GammaGamma" in parameterName :
             process+=insert_ME("MEGammaGamma")
             process+="set /Herwig/Cuts/PhotonKtCut:MinKT 5.\n"
             parameterName=parameterName.replace("-GammaGamma","")
         elif "DiPhoton-GammaJet" in parameterName :
             process+=insert_ME("MEGammaJet")
             process+="set /Herwig/Cuts/PhotonKtCut:MinKT 5.\n"
             parameterName=parameterName.replace("-GammaJet","")
         elif "8-WH" in parameterName :
             process+=insert_ME("MEPP2WH")
             process+=jet_kt_cut(0.0)
             if "GammaGamma" in parameterName :
                process+=selectDecayMode("h0",["h0->gamma,gamma;"])
                addedBRReweighter = True
             elif "WW" in parameterName :
                process+=selectDecayMode("h0",["h0->W+,W-;"])
                addedBRReweighter = True
             elif "ZZ" in parameterName :
                process+=selectDecayMode("h0",["h0->Z0,Z0;"])
                addedBRReweighter = True
         elif "8-ZH" in parameterName :
             process+=insert_ME("MEPP2ZH")
             process+=jet_kt_cut(0.0)
             if "GammaGamma" in parameterName :
                process+=selectDecayMode("h0",["h0->gamma,gamma;"])
                addedBRReweighter = True
             elif "WW" in parameterName :
                process+=selectDecayMode("h0",["h0->W+,W-;"])
                addedBRReweighter = True
             elif "ZZ" in parameterName :
                process+=selectDecayMode("h0",["h0->Z0,Z0;"])
                addedBRReweighter = True
         elif "WH" in parameterName :
             process+=selectDecayMode("h0",["h0->b,bbar;"])
             process+=selectDecayMode("W+",["W+->nu_e,e+;",
                                            "W+->nu_mu,mu+;"])
             addedBRReweighter = True
             process+=insert_ME("MEPP2WH")
             process+=jet_kt_cut(0.0)
         elif "ZH" in parameterName :
             process+=selectDecayMode("h0",["h0->b,bbar;"])
             process+=selectDecayMode("Z0",["Z0->e-,e+;",
                                            "Z0->mu-,mu+;"])
             addedBRReweighter = True
             process+=insert_ME("MEPP2ZH")
             process+=jet_kt_cut(0.0)
         elif "UE"  in parameterName or "Cent" in parameterName :
             if "Dipole" in parameters["shower"]:
                 process+="read snippets/MB-DipoleShower.in\n"
             else:
                 process+="set /Herwig/Shower/ShowerHandler:IntrinsicPtGaussian 2.2*GeV\n"                
                 process+="read snippets/MB.in\n"
             process+="read snippets/Diffraction.in\n"
             if "Long" in parameterName :
                 process += "set /Herwig/Decays/DecayHandler:MaxLifeTime 100*mm\n"
         elif "8-DiJets" in parameterName or "7-DiJets" in parameterName or "13-DiJets" in parameterName :
             process+=insert_ME("MEQCD2to2")
             process+="set MEQCD2to2:MaximumFlavour 5\n"
             process+="set /Herwig/UnderlyingEvent/MPIHandler:IdenticalToUE 0\n"
             if "13-DiJets" not in parameterName :
                 if "-A" in parameterName :
                     process+=jet_kt_cut(45.)
                     process+="set /Herwig/Cuts/JetKtCut:MinEta -3.\n"
                     process+="set /Herwig/Cuts/JetKtCut:MaxEta  3.\n"
                 elif "-B" in parameterName :
                     process+=jet_kt_cut(20.)
                     process+="set /Herwig/Cuts/JetKtCut:MinEta -2.7\n"
                     process+="set /Herwig/Cuts/JetKtCut:MaxEta  2.7\n"
                 elif "-C" in parameterName :
                     process+=jet_kt_cut(20.)
                     process+="set /Herwig/Cuts/JetKtCut:MinEta -4.8\n"
                     process+="set /Herwig/Cuts/JetKtCut:MaxEta  4.8\n"
             else :
                 if "-A" in parameterName :
                     process+=jet_kt_cut(60.)
                     process+="set /Herwig/Cuts/JetKtCut:MinEta -3.\n"
                     process+="set /Herwig/Cuts/JetKtCut:MaxEta  3.\n"
                 elif "-B" in parameterName :
                     process+=jet_kt_cut(180.)
                     process+="set /Herwig/Cuts/JetKtCut:MinEta -3.\n"
                     process+="set /Herwig/Cuts/JetKtCut:MaxEta  3.\n"
                 
             if "DiJets-1" in parameterName   : process+=mhat_cut(90.)
             elif "DiJets-2" in parameterName : process+=mhat_cut(200.)
             elif "DiJets-3" in parameterName : process+=mhat_cut(450.)
             elif "DiJets-4" in parameterName : process+=mhat_cut(750.)
             elif "DiJets-5" in parameterName : process+=mhat_cut(950.)
             elif "DiJets-6" in parameterName : process+=mhat_cut(1550.)
             elif "DiJets-7" in parameterName : process+=mhat_cut(2150.)
             elif "DiJets-8" in parameterName : process+=mhat_cut(2750.)
             elif "DiJets-9" in parameterName : process+=mhat_cut(3750.)
             elif "DiJets-10" in parameterName : process+=mhat_cut(4750.)
             elif "DiJets-11" in parameterName : process+=mhat_cut(5750.)
         elif(      "7-Jets" in parameterName 
                or  "8-Jets" in parameterName 
                or "13-Jets" in parameterName 
                or "2760-Jets" in parameterName 
             ) :
             process+=insert_ME("MEQCD2to2")
             process+="set MEQCD2to2:MaximumFlavour 5\n"
             process+="set /Herwig/UnderlyingEvent/MPIHandler:IdenticalToUE 0\n"
             if "Jets-10" in parameterName  : process+=jet_kt_cut(1800.)
             elif "Jets-0" in parameterName : process+=jet_kt_cut(5.)
             elif "Jets-1" in parameterName : process+=jet_kt_cut(10.)
             elif "Jets-2" in parameterName : process+=jet_kt_cut(20.)
             elif "Jets-3" in parameterName : process+=jet_kt_cut(40.)
             elif "Jets-4" in parameterName : process+=jet_kt_cut(70.)
             elif "Jets-5" in parameterName : process+=jet_kt_cut(150.)
             elif "Jets-6" in parameterName : process+=jet_kt_cut(200.)
             elif "Jets-7" in parameterName : process+=jet_kt_cut(300.)
             elif "Jets-8" in parameterName : process+=jet_kt_cut(500.)
             elif "Jets-9" in parameterName : process+=jet_kt_cut(800.)
         elif( "-Charm" in parameterName  or "-Bottom" in parameterName ) :
             
             if("8-Bottom" in parameterName) :
                 addBRReweighter()
                 process+=selectDecayMode("Jpsi",["Jpsi->mu-,mu+;"])
                 
             if "Bottom" in parameterName :
                 process+="cp MEHeavyQuark MEBottom\n" 
                 process+="set MEBottom:QuarkType Bottom\n"
                 process+=insert_ME("MEBottom")
             else : 
                 process+="cp MEHeavyQuark MECharm\n" 
                 process+="set MECharm:QuarkType Charm\n"
                 process+=insert_ME("MECharm")
             process+="set /Herwig/UnderlyingEvent/MPIHandler:IdenticalToUE 0\n"
             if "-0" in parameterName :
                 if "Bottom" in parameterName :
                     process+="set MEBottom:Process Pair\n"
                     process+=jet_kt_cut(0.)
                 else :
                     process+=jet_kt_cut(1.)
             elif "-1" in parameterName : process+=jet_kt_cut(5.)
             elif "-2" in parameterName : process+=jet_kt_cut(15.)
             elif "-3" in parameterName : process+=jet_kt_cut(20.)
             elif "-4" in parameterName : process+=jet_kt_cut(50.)
             elif "-5" in parameterName : process+=jet_kt_cut(80.)
             elif "-6" in parameterName : process+=jet_kt_cut(110.)
             elif "-7" in parameterName : process+=jet_kt_cut(30.)+mhat_cut(90.)
             elif "-8" in parameterName : process+=jet_kt_cut(30.)+mhat_cut(340.)
             elif "-9" in parameterName : process+=jet_kt_cut(30.)+mhat_cut(500.)
         elif "Top-L" in parameterName :
             process+="set MEHeavyQuark:QuarkType Top\n"
             process+=insert_ME("MEHeavyQuark")
             process+=selectDecayMode("t",["t->nu_e,e+,b;",
                                           "t->nu_mu,mu+,b;"])
             process+=addBRReweighter()
             
         elif "Top-SL" in parameterName :
             process+="set MEHeavyQuark:QuarkType Top\n"
             process+=insert_ME("MEHeavyQuark")
             process+="set /Herwig/Particles/t:Synchronized Not_synchronized\n"
             process+="set /Herwig/Particles/tbar:Synchronized Not_synchronized\n"
             process+=selectDecayMode("t",["t->nu_e,e+,b;","t->nu_mu,mu+,b;"])
             process+=selectDecayMode("tbar",["tbar->b,bbar,cbar;",
                                              "tbar->bbar,cbar,d;",
                                              "tbar->bbar,cbar,s;",
                                              "tbar->bbar,s,ubar;",
                                              "tbar->bbar,ubar,d;"])
             process+=addBRReweighter()
             
         elif "Top-All" in parameterName :
             process+="set MEHeavyQuark:QuarkType Top\n"
             process+=insert_ME("MEHeavyQuark")
         elif "WZ" in parameterName :
             process+=insert_ME("MEPP2VV","WZ")
             process+=selectDecayMode("W+",["W+->nu_e,e+;",
                                            "W+->nu_mu,mu+;"])
             process+=selectDecayMode("W-",["W-->nu_ebar,e-;",
                                            "W-->nu_mubar,mu-;"])
             process+=selectDecayMode("Z0",["Z0->e-,e+;",
                                            "Z0->mu-,mu+;"])
             addedBRReweighter = True
             
         elif "WW-emu" in parameterName :
             process+=insert_ME("MEPP2VV","WW")
             process+="set /Herwig/Particles/W+:Synchronized 0\n"
             process+="set /Herwig/Particles/W-:Synchronized 0\n"
             process+=selectDecayMode("W+",["W+->nu_e,e+;"])
             process+=selectDecayMode("W-",["W-->nu_mubar,mu-;"])
             addedBRReweighter = True
             
         elif "WW-ll" in parameterName :
             process+=insert_ME("MEPP2VV","WW")
             process+=selectDecayMode("W+",["W+->nu_e,e+;","W+->nu_mu,mu+;","W+->nu_tau,tau+;"])
             addedBRReweighter = True
             
         elif "ZZ-ll" in parameterName :
             process+=insert_ME("MEPP2VV","ZZ")
             process+=selectDecayMode("Z0",["Z0->e-,e+;",
                                            "Z0->mu-,mu+;",
                                            "Z0->tau-,tau+;"])
             addedBRReweighter = True
 
         elif "ZZ-lv" in parameterName :
             process+=insert_ME("MEPP2VV","ZZ")
             process+=selectDecayMode("Z0",["Z0->e-,e+;",
                                            "Z0->mu-,mu+;",
                                            "Z0->tau-,tau+;",
                                            "Z0->nu_e,nu_ebar;",
                                            "Z0->nu_mu,nu_mubar;",
                                            "Z0->nu_tau,nu_taubar;"])
             addedBRReweighter = True
         elif "W-e" in parameterName :
             process+=insert_ME("MEqq2W2ff","Electron")
         elif "W-mu" in parameterName :
             process+=insert_ME("MEqq2W2ff","Muon")
         elif "Z-e" in parameterName or "Z-mu" in parameterName :
             if "Z-e" in parameterName:
                 process+=insert_ME("MEqq2gZ2ff","Electron")
             else :
                 process+=insert_ME("MEqq2gZ2ff","Muon")
             mcuts=[10,35,75,110,400,ecms]
             for i in range(1,6) :
                 tstring = "-Mass%s"%i
                 if tstring in parameterName :
                     process+=mhat_minm_maxm(mcuts[i-1],mcuts[i-1],mcuts[i])
                     parameterName=parameterName.replace(tstring,"")
         elif "Z-nu" in parameterName :
             process+=insert_ME("MEqq2gZ2ff","Neutrinos")
         elif "W-Jet" in parameterName :
             process+=insert_ME("MEWJet","Electron","WDecay")
             if "W-Jet-1-e" in parameterName :
                 process+="set /Herwig/Cuts/WBosonKtCut:MinKT 100.0*GeV\n"
                 parameterName=parameterName.replace("W-Jet-1-e","W-Jet-e")
             elif "W-Jet-2-e" in parameterName :
                 process+="set /Herwig/Cuts/WBosonKtCut:MinKT 190.0*GeV\n"
                 parameterName=parameterName.replace("W-Jet-2-e","W-Jet-e")
             elif "W-Jet-3-e" in parameterName :
                 process+="set /Herwig/Cuts/WBosonKtCut:MinKT 270.0*GeV\n"
                 parameterName=parameterName.replace("W-Jet-3-e","W-Jet-e")
         elif "Z-Jet" in parameterName :
             if "-e" in parameterName :
                 process+=insert_ME("MEZJet","Electron","ZDecay")
                 if "Z-Jet-0-e" in parameterName :
                     process+="set /Herwig/Cuts/ZBosonKtCut:MinKT 35.0*GeV\n"
                     parameterName=parameterName.replace("Z-Jet-0-e","Z-Jet-e")
                 elif "Z-Jet-1-e" in parameterName :
                     process+="set /Herwig/Cuts/ZBosonKtCut:MinKT 100.0*GeV\n"
                     parameterName=parameterName.replace("Z-Jet-1-e","Z-Jet-e")
                 elif "Z-Jet-2-e" in parameterName :
                     process+="set /Herwig/Cuts/ZBosonKtCut:MinKT 190.0*GeV\n"
                     parameterName=parameterName.replace("Z-Jet-2-e","Z-Jet-e")
                 elif "Z-Jet-3-e" in parameterName :
                     process+="set /Herwig/Cuts/ZBosonKtCut:MinKT 270.0*GeV\n"
                     parameterName=parameterName.replace("Z-Jet-3-e","Z-Jet-e")
             else :
                 process+=insert_ME("MEZJet","Muon","ZDecay")
                 process+="set /Herwig/Cuts/ZBosonKtCut:MinKT 35.0*GeV\n"
                 parameterName=parameterName.replace("Z-Jet-0-mu","Z-Jet-mu")
         elif "WGamma" in parameterName :
             process+=insert_ME("MEPP2VGamma","1")
             process+="set MEPP2VGamma:MassOption 1"
             process+="set /Herwig/Cuts/PhotonKtCut:MinKT 10.\n"
             
             
             if "-e" in parameterName :
                 process+=selectDecayMode("W+",["W+->nu_e,e+;"])
                 addedBRReweighter=True
             else :
                 process+=selectDecayMode("W+",["W+->nu_mu,mu+;"])
                 addedBRReweighter=True
         elif "ZGamma" in parameterName :
             process+=insert_ME("MEPP2VGamma","2")
             process+="set /Herwig/Cuts/PhotonKtCut:MinKT 10.\n"
             if "-e" in parameterName :
                 process+=selectDecayMode("Z0",["Z0->e-,e+;"])
                 addedBRReweighter=True
             else :
                 process+=selectDecayMode("Z0",["Z0->mu-,mu+;"])
                 addedBRReweighter=True
         else :
             logging.error(" Process %s not supported for internal matrix elements" % name)
             sys.exit(1)
     elif(simulation=="Powheg") :
         if "VBF" in parameterName :
             process+=insert_ME("PowhegMEPP2HiggsVBF")
             if "GammaGamma" in parameterName :
                process+=selectDecayMode("h0",["h0->gamma,gamma;"])
                addedBRReweighter = True
             elif "WW" in parameterName :
                process+=selectDecayMode("h0",["h0->W+,W-;"])
                addedBRReweighter = True
             elif "ZZ" in parameterName :
                process+=selectDecayMode("h0",["h0->Z0,Z0;"])
                addedBRReweighter = True
             elif "8-" not in parameterName :
                 process+=selectDecayMode("h0",["h0->tau-,tau+;"])
                 addedBRReweighter = True
                 process+="set /Herwig/Particles/tau-:Stable Stable\n"
             
         elif "ggHJet" in parameterName :
             logging.error(" Process %s not supported for POWHEG matrix elements" % name)
             sys.exit(1)
         elif "ggH" in parameterName :
             process+=insert_ME("PowhegMEHiggs")
             if "GammaGamma" in parameterName :
                process+=selectDecayMode("h0",["h0->gamma,gamma;"])
                addedBRReweighter = True
             elif "WW" in parameterName :
                process+=selectDecayMode("h0",["h0->W+,W-;"])
                addedBRReweighter = True
             elif "ZZ" in parameterName :
                process+=selectDecayMode("h0",["h0->Z0,Z0;"])
                addedBRReweighter = True
             elif "8-" not in parameterName :
                 process+=selectDecayMode("h0",["h0->tau-,tau+;"])
                 addedBRReweighter = True
                 process+="set /Herwig/Particles/tau-:Stable Stable\n"
         elif "8-WH" in parameterName :
             process+=insert_ME("PowhegMEPP2WH")
             process+=jet_kt_cut(0.0)
             if "GammaGamma" in parameterName :
                process+=selectDecayMode("h0",["h0->gamma,gamma;"])
                addedBRReweighter = True
             elif "WW" in parameterName :
                process+=selectDecayMode("h0",["h0->W+,W-;"])
                addedBRReweighter = True
             elif "ZZ" in parameterName :
                process+=selectDecayMode("h0",["h0->Z0,Z0;"])
                addedBRReweighter = True
         elif "8-ZH" in parameterName :
             process+=insert_ME("PowhegMEPP2ZH")
             process+=jet_kt_cut(0.0)
             if "GammaGamma" in parameterName :
                process+=selectDecayMode("h0",["h0->gamma,gamma;"])
                addedBRReweighter = True
             elif "WW" in parameterName :
                process+=selectDecayMode("h0",["h0->W+,W-;"])
                addedBRReweighter = True
             elif "ZZ" in parameterName :
                process+=selectDecayMode("h0",["h0->Z0,Z0;"])
                addedBRReweighter = True
         elif "WH" in parameterName :
             process+=selectDecayMode("h0",["h0->b,bbar;"])
             process+=selectDecayMode("W+",["W+->nu_e,e+;",
                                            "W+->nu_mu,mu+;"])
             addedBRReweighter = True
             process+=insert_ME("PowhegMEPP2WH")
             process+=jet_kt_cut(0.0)
         elif "ZH" in parameterName :
             process+=selectDecayMode("h0",["h0->b,bbar;"])
             process+=selectDecayMode("Z0",["Z0->e-,e+;",
                                            "Z0->mu-,mu+;"])
             addedBRReweighter = True
             process+=insert_ME("PowhegMEPP2ZH")
             process+=jet_kt_cut(0.0)
         elif "UE" in parameterName :
             logging.error(" Process %s not supported for powheg matrix elements" % name)
             sys.exit(1)
         elif "WZ" in parameterName :
             process+="create Herwig::HwDecayHandler /Herwig/NewPhysics/DecayHandler\n"
             process+="set /Herwig/NewPhysics/DecayHandler:NewStep No\n"
             process+="set /Herwig/Shower/ShowerHandler:SplitHardProcess No\n";
             process+="set /Herwig/Decays/ZDecayer:PhotonGenerator NULL\n";
             process+="set /Herwig/Decays/WDecayer:PhotonGenerator NULL\n";
             process+="insert /Herwig/NewPhysics/DecayHandler:Excluded 0 /Herwig/Particles/tau-\n"
             process+="insert /Herwig/NewPhysics/DecayHandler:Excluded 1 /Herwig/Particles/tau+\n"
             process+="insert /Herwig/Generators/EventGenerator:EventHandler:PreCascadeHandlers 0 /Herwig/NewPhysics/DecayHandler\n"
             process+=insert_ME("PowhegMEPP2VV","WZ")
             process+=selectDecayMode("W+",["W+->nu_e,e+;",
                                            "W+->nu_mu,mu+;"])
             process+=selectDecayMode("W-",["W-->nu_ebar,e-;",
                                            "W-->nu_mubar,mu-;"])
             process+=selectDecayMode("Z0",["Z0->e-,e+;",
                                            "Z0->mu-,mu+;"])
             addedBRReweighter = True
             
         elif "WW-emu" in parameterName :
             process+="create Herwig::HwDecayHandler /Herwig/NewPhysics/DecayHandler\n"
             process+="set /Herwig/NewPhysics/DecayHandler:NewStep No\n"
             process+="set /Herwig/Shower/ShowerHandler:SplitHardProcess No\n";
             process+="set /Herwig/Decays/ZDecayer:PhotonGenerator NULL\n";
             process+="set /Herwig/Decays/WDecayer:PhotonGenerator NULL\n";
             process+="insert /Herwig/NewPhysics/DecayHandler:Excluded 0 /Herwig/Particles/tau-\n"
             process+="insert /Herwig/NewPhysics/DecayHandler:Excluded 1 /Herwig/Particles/tau+\n"
             process+="insert /Herwig/Generators/EventGenerator:EventHandler:PreCascadeHandlers 0 /Herwig/NewPhysics/DecayHandler\n"
             process+=insert_ME("PowhegMEPP2VV","WW")
             process+="set /Herwig/Particles/W+:Synchronized 0\n"
             process+="set /Herwig/Particles/W-:Synchronized 0\n"
             process+=selectDecayMode("W+",["W+->nu_e,e+;"])
             process+=selectDecayMode("W-",["W-->nu_mubar,mu-;"])
             addedBRReweighter = True
             
         elif "WW-ll" in parameterName :
             process+="create Herwig::HwDecayHandler /Herwig/NewPhysics/DecayHandler\n"
             process+="set /Herwig/NewPhysics/DecayHandler:NewStep No\n"
             process+="set /Herwig/Shower/ShowerHandler:SplitHardProcess No\n";
             process+="set /Herwig/Decays/ZDecayer:PhotonGenerator NULL\n";
             process+="set /Herwig/Decays/WDecayer:PhotonGenerator NULL\n";
             process+="insert /Herwig/NewPhysics/DecayHandler:Excluded 0 /Herwig/Particles/tau-\n"
             process+="insert /Herwig/NewPhysics/DecayHandler:Excluded 1 /Herwig/Particles/tau+\n"
             process+="insert /Herwig/Generators/EventGenerator:EventHandler:PreCascadeHandlers 0 /Herwig/NewPhysics/DecayHandler\n"
             process+=insert_ME("PowhegMEPP2VV","WW")
             process+=selectDecayMode("W+",["W+->nu_e,e+;",
                                            "W+->nu_mu,mu+;",
                                            "W+->nu_tau,tau+;"])
             addedBRReweighter = True
             
         elif "ZZ-ll" in parameterName :
             process+="create Herwig::HwDecayHandler /Herwig/NewPhysics/DecayHandler\n"
             process+="set /Herwig/NewPhysics/DecayHandler:NewStep No\n"
             process+="set /Herwig/Shower/ShowerHandler:SplitHardProcess No\n";
             process+="set /Herwig/Decays/ZDecayer:PhotonGenerator NULL\n";
             process+="set /Herwig/Decays/WDecayer:PhotonGenerator NULL\n";
             process+="insert /Herwig/NewPhysics/DecayHandler:Excluded 0 /Herwig/Particles/tau-\n"
             process+="insert /Herwig/NewPhysics/DecayHandler:Excluded 1 /Herwig/Particles/tau+\n"
             process+="insert /Herwig/Generators/EventGenerator:EventHandler:PreCascadeHandlers 0 /Herwig/NewPhysics/DecayHandler\n"
             process+=insert_ME("PowhegMEPP2VV","ZZ")
             process+=selectDecayMode("Z0",["Z0->e-,e+;",
                                            "Z0->mu-,mu+;",
                                            "Z0->tau-,tau+;"])
             addedBRReweighter = True
             
         elif "ZZ-lv" in parameterName :
             process+="create Herwig::HwDecayHandler /Herwig/NewPhysics/DecayHandler\n"
             process+="set /Herwig/NewPhysics/DecayHandler:NewStep No\n"
             process+="set /Herwig/Shower/ShowerHandler:SplitHardProcess No\n";
             process+="set /Herwig/Decays/ZDecayer:PhotonGenerator NULL\n";
             process+="set /Herwig/Decays/WDecayer:PhotonGenerator NULL\n";
             process+="insert /Herwig/NewPhysics/DecayHandler:Excluded 0 /Herwig/Particles/tau-\n"
             process+="insert /Herwig/NewPhysics/DecayHandler:Excluded 1 /Herwig/Particles/tau+\n"
             process+="insert /Herwig/Generators/EventGenerator:EventHandler:PreCascadeHandlers 0 /Herwig/NewPhysics/DecayHandler\n"
             process+=insert_ME("PowhegMEPP2VV","ZZ")
             process+=selectDecayMode("Z0",["Z0->e-,e+;",
                                            "Z0->mu-,mu+;",
                                            "Z0->tau-,tau+;",
                                            "Z0->nu_e,nu_ebar;",
                                            "Z0->nu_mu,nu_mubar;",
                                            "Z0->nu_tau,nu_taubar;"])
             addedBRReweighter = True
         elif "W-e" in parameterName :
             process+=insert_ME("PowhegMEqq2W2ff","Electron")
         elif "W-mu" in parameterName :
             process+=insert_ME("PowhegMEqq2W2ff","Muon")
         elif "Z-e" in parameterName or "Z-mu" in parameterName :
             if "Z-e" in parameterName:
                 process+=insert_ME("PowhegMEqq2gZ2ff","Electron")
             else :
                 process+=insert_ME("PowhegMEqq2gZ2ff","Muon")
             mcuts=[10,35,75,110,400,ecms]
             for i in range(1,6) :
                 tstring = "-Mass%s"%i
                 if tstring in parameterName :
                     process+=mhat_minm_maxm(mcuts[i-1],mcuts[i-1],mcuts[i])
                     parameterName=parameterName.replace(tstring,"")
         elif "Z-nu" in parameterName :
             process+=insert_ME("PowhegMEqq2gZ2ff","Neutrinos")
         elif "DiPhoton-GammaGamma" in parameterName :
             process+=insert_ME("MEGammaGammaPowheg","GammaGamma")
             process+=insert_ME("MEGammaGamma","gg")
             process+="set /Herwig/Cuts/PhotonKtCut:MinKT 5.\n"
             process+=jet_kt_cut(5.)
             parameterName=parameterName.replace("-GammaGamma","")
         elif "DiPhoton-GammaJet" in parameterName :
             process+=insert_ME("MEGammaGammaPowheg","VJet")
             process+="set /Herwig/Cuts/PhotonKtCut:MinKT 5.\n"
             process+=jet_kt_cut(5.)
             parameterName=parameterName.replace("-GammaJet","")
         else :
             logging.error(" Process %s not supported for internal POWHEG matrix elements" % name)
             sys.exit(1)
             
     elif( simulation=="Matchbox" or simulation=="Merging" ) :
         if "VBF" in parameterName :
             parameters["nlo"] = "read Matchbox/VBFNLO.in\n"
             if(simulation=="Merging"):
                 process+="cd /Herwig/Merging/\n"
             process+="insert "+thefactory+":DiagramGenerator:RestrictLines 0 /Herwig/Particles/Z0\n"
             process+="insert "+thefactory+":DiagramGenerator:RestrictLines 0 /Herwig/Particles/W+\n"
             process+="insert "+thefactory+":DiagramGenerator:RestrictLines 0 /Herwig/Particles/W-\n"
             process+="insert "+thefactory+":DiagramGenerator:RestrictLines 0 /Herwig/Particles/gamma\n"
             process+="do "+thefactory+":DiagramGenerator:TimeLikeRange 0 0\n"
             if(simulation=="Matchbox"):
                 process+=addProcess(thefactory,"p p h0 j j","0","3","FixedScale",0,0)
             elif(simulation=="Merging"):
                 process+=addProcess(thefactory,"p p h0 j j","0","3","FixedScale",1,1)
             process+=setHardProcessWidthToZero(["h0"])
             process+="set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 125.7\n"
             if "GammaGamma" in parameterName :
                process+=selectDecayMode("h0",["h0->gamma,gamma;"])
                process+=addBRReweighter()
             elif "WW" in parameterName :
                process+=selectDecayMode("h0",["h0->W+,W-;"])
                process+=addBRReweighter()
             elif "ZZ" in parameterName :
                process+=selectDecayMode("h0",["h0->Z0,Z0;"])
                process+=addBRReweighter()
             elif "8-" not in parameterName :
                 process+=selectDecayMode("h0",["h0->tau-,tau+;"])
                 process+=addBRReweighter()
                 process+="set /Herwig/Particles/tau-:Stable Stable\n"
         elif "ggHJet" in parameterName :
             if(simulation=="Merging"):
                logging.warning("ggHJet not explicitly tested for %s " % simulation)
                sys.exit(0)
             parameters["nlo"] = "read Matchbox/MadGraph-GoSam.in\nread Matchbox/HiggsEffective.in\n"
             process+=selectDecayMode("h0",["h0->tau-,tau+;"])
             process+=addBRReweighter()
             process+="set /Herwig/Particles/tau-:Stable Stable\n"
             process+=setHardProcessWidthToZero(["h0"])
             process+=addProcess(thefactory,"p p h0 j","3","1","FixedScale",0,0)
             process+=addFirstJet("20")
             process+="set "+thefactory+":ScaleChoice /Herwig/MatrixElements/Matchbox/Scales/FixedScale\n"
             process+="set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 125.7\n"
         elif "ggH" in parameterName :
             parameters["nlo"] = "read Matchbox/MadGraph-GoSam.in\nread Matchbox/HiggsEffective.in\n"
             if(simulation=="Merging"):
                 process+= "cd /Herwig/MatrixElements/Matchbox/Amplitudes\nset OpenLoops:HiggsEff Yes\nset MadGraph:Model heft\n"
                 process+="cd /Herwig/Merging/\n"
             process+=setHardProcessWidthToZero(["h0"])
             if(simulation=="Matchbox"):
                 process+=addProcess(thefactory,"p p h0","2","1","FixedScale",0,0)
             elif(simulation=="Merging"):
                 process+=addProcess(thefactory,"p p h0","2","1","FixedScale",2,2)
             process+="set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 125.7\n"
             if "GammaGamma" in parameterName :
                process+=selectDecayMode("h0",["h0->gamma,gamma;"])
                process+=addBRReweighter()
             elif "WW" in parameterName :
                process+=selectDecayMode("h0",["h0->W+,W-;"])
                process+=addBRReweighter()
             elif "ZZ" in parameterName :
                process+=selectDecayMode("h0",["h0->Z0,Z0;"])
                process+=addBRReweighter()
             elif "8-" not in parameterName :
                 process+=selectDecayMode("h0",["h0->tau-,tau+;"])
                 process+=addBRReweighter()
                 process+="set /Herwig/Particles/tau-:Stable Stable\n"
         elif "8-WH" in parameterName :
             if(simulation=="Merging"):
               logging.warning("8-WH not explicitly tested for %s " % simulation)
               sys.exit(0)
             process+=setHardProcessWidthToZero(["h0","W+","W-"])
             process+=addProcess(thefactory,"p p W+ h0","0","2","FixedScale",0,0)
             process+=addProcess(thefactory,"p p W- h0","0","2","FixedScale",0,0)
             process+="set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 125.7\n"
             if "GammaGamma" in parameterName :
                process+=selectDecayMode("h0",["h0->gamma,gamma;"])
                process+=addBRReweighter()
             elif "WW" in parameterName :
                process+=selectDecayMode("h0",["h0->W+,W-;"])
                process+=addBRReweighter()
             elif "ZZ" in parameterName :
                process+=selectDecayMode("h0",["h0->Z0,Z0;"])
                process+=addBRReweighter()
                
         elif "8-ZH" in parameterName :
             if(simulation=="Merging"):
               logging.warning("8-ZH not explicitly tested for %s " % simulation)
               sys.exit(0)
             process+=setHardProcessWidthToZero(["h0","Z0"])
             process+=addProcess(thefactory,"p p Z0 h0","0","2","FixedScale",0,0)
             process+="set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 125.7\n"
             if "GammaGamma" in parameterName :
                process+=selectDecayMode("h0",["h0->gamma,gamma;"])
                process+=addBRReweighter()
             elif "WW" in parameterName :
                process+=selectDecayMode("h0",["h0->W+,W-;"])
                process+=addBRReweighter()
             elif "ZZ" in parameterName :
                process+=selectDecayMode("h0",["h0->Z0,Z0;"])
                process+=addBRReweighter()
                
         elif "WH" in parameterName :
             if(simulation=="Merging"):
               logging.warning("WH not explicitly tested for %s " % simulation)
               sys.exit(0)
             process+=selectDecayMode("h0",["h0->b,bbar;"])
             process+=addBRReweighter()
             process+=setHardProcessWidthToZero(["h0"])
             process+=addProcess(thefactory,"p p e+ nu h0","0","3","LeptonPairMassScale",0,0)
             process+=addProcess(thefactory,"p p e- nu h0","0","3","LeptonPairMassScale",0,0)
             process+=addProcess(thefactory,"p p mu+ nu h0","0","3","LeptonPairMassScale",0,0)
             process+=addProcess(thefactory,"p p mu- nu h0","0","3","LeptonPairMassScale",0,0)
             process+=addLeptonPairCut("60","120")
         elif "ZH" in parameterName :
             if(simulation=="Merging"):
               logging.warning("ZH not explicitly tested for %s " % simulation)
               sys.exit(0)
             process+=selectDecayMode("h0",["h0->b,bbar;"])
             process+=addBRReweighter()
             process+=setHardProcessWidthToZero(["h0"])
             process+=addProcess(thefactory,"p p e+ e- h0","0","3","LeptonPairMassScale",0,0)
             process+=addProcess(thefactory,"p p mu+ mu- h0","0","3","LeptonPairMassScale",0,0)
             process+=addLeptonPairCut("60","120")
         elif "UE" in parameterName :
             logging.error(" Process %s not supported for Matchbox matrix elements" % name)
             sys.exit(1)
         elif "8-DiJets" in parameterName or "7-DiJets" in parameterName or "13-DiJets" in parameterName :
             if(simulation=="Matchbox"):
               process+=addProcess(thefactory,"p p j j","2","0","MaxJetPtScale",0,0)
             elif(simulation=="Merging"):
               process+=addProcess(thefactory,"p p j j","2","0","MaxJetPtScale",1,1)
             process+="set /Herwig/UnderlyingEvent/MPIHandler:IdenticalToUE 0\n"
             if "13-DiJets" not in parameterName :
                 if "-A" in parameterName :
                     process+=addFirstJet("45")
                     process+=addSecondJet("25")
                     process+="set /Herwig/Cuts/FirstJet:YRange  -3. 3.\n"
                     process+="set /Herwig/Cuts/SecondJet:YRange -3. 3.\n"
                 elif "-B" in parameterName :
                     process+=addFirstJet("20")
                     process+=addSecondJet("15")
                     process+="set /Herwig/Cuts/FirstJet:YRange  -2.7 2.7\n"
                     process+="set /Herwig/Cuts/SecondJet:YRange -2.7 2.7\n"
                 elif "-C" in parameterName :
                     process+=addFirstJet("20")
                     process+=addSecondJet("15")
                     process+="set /Herwig/Cuts/FirstJet:YRange  -4.8 4.8\n"
                     process+="set /Herwig/Cuts/SecondJet:YRange -4.8 4.8\n"
                 else :
                     logging.error("Exit 00001")
                     sys.exit(1)
             else :
                 if "-A" in parameterName :
                     process+= addFirstJet("75.")
                     process+=addSecondJet("60.")
                     process+="set /Herwig/Cuts/JetKtCut:MinEta -3.\n"
                     process+="set /Herwig/Cuts/JetKtCut:MaxEta  3.\n"
                 elif "-B" in parameterName :
                     process+= addFirstJet("220.")
                     process+=addSecondJet("180.")
                     process+="set /Herwig/Cuts/JetKtCut:MinEta -3.\n"
                     process+="set /Herwig/Cuts/JetKtCut:MaxEta  3.\n"
                 else :
                     logging.error("Exit 00001")
                     sys.exit(1)
 
                     
             if "DiJets-1" in parameterName   : process+=addJetPairCut("90")
             elif "DiJets-2" in parameterName : process+=addJetPairCut("200")
             elif "DiJets-3" in parameterName : process+=addJetPairCut("450")
             elif "DiJets-4" in parameterName : process+=addJetPairCut("750")
             elif "DiJets-5" in parameterName : process+=addJetPairCut("950")
             elif "DiJets-6" in parameterName : process+=addJetPairCut("1550")
             elif "DiJets-7" in parameterName : process+=addJetPairCut("2150")
             elif "DiJets-8" in parameterName : process+=addJetPairCut("2750")
             elif "DiJets-9" in parameterName : process+=mhat_cut(3750.)
             elif "DiJets-10" in parameterName : process+=mhat_cut(4750.)
             elif "DiJets-11" in parameterName : process+=mhat_cut(5750.)
             else :
                 logging.error("Exit 00002")
                 sys.exit(1)
 
 
         elif(      "7-Jets" in parameterName 
                or  "8-Jets" in parameterName 
                or "13-Jets" in parameterName 
                or "2760-Jets" in parameterName 
             ) :
             if(simulation=="Matchbox"):
                 process+=addProcess(thefactory,"p p j j","2","0","MaxJetPtScale",0,0)
             elif(simulation=="Merging"):
                 process+=addProcess(thefactory,"p p j j","2","0","MaxJetPtScale",1,1)
             process+="set /Herwig/UnderlyingEvent/MPIHandler:IdenticalToUE 0\n"
             if "Jets-10" in parameterName  : process+=addFirstJet("1800")
             elif "Jets-0" in parameterName : process+=addFirstJet("5")
             elif "Jets-1" in parameterName : process+=addFirstJet("10")
             elif "Jets-2" in parameterName : process+=addFirstJet("20")
             elif "Jets-3" in parameterName : process+=addFirstJet("40")
             elif "Jets-4" in parameterName : process+=addFirstJet("70")
             elif "Jets-5" in parameterName : process+=addFirstJet("150")
             elif "Jets-6" in parameterName : process+=addFirstJet("200")
             elif "Jets-7" in parameterName : process+=addFirstJet("300")
             elif "Jets-8" in parameterName : process+=addFirstJet("500")
             elif "Jets-9" in parameterName : process+=addFirstJet("800")
             else :
                 logging.error("Exit 00003")
                 sys.exit(1)
         elif(     "-Charm" in parameterName or "-Bottom" in parameterName) :
             parameters["bscheme"]=fourFlavour
             process+="set /Herwig/Particles/b:HardProcessMass 4.2*GeV\n"
             process+="set /Herwig/Particles/bbar:HardProcessMass 4.2*GeV\n"
             
             if("8-Bottom" in parameterName) :
                 addBRReweighter()
                 process+=selectDecayMode("Jpsi",["Jpsi->mu-,mu+;"])
             
             if "Bottom" in parameterName :
                 if(simulation=="Matchbox"):
                     process+=addProcess(thefactory,"p p b bbar","2","0","MaxJetPtScale",0,0)
                 elif(simulation=="Merging"):
                     process+=addProcess(thefactory,"p p b bbar","2","0","MaxJetPtScale",1,0)
             else:
                 if(simulation=="Matchbox"):
                     process+=addProcess(thefactory,"p p c cbar","2","0","MaxJetPtScale",0,0)
                 elif(simulation=="Merging"):
                     process+=addProcess(thefactory,"p p c cbar","2","0","MaxJetPtScale",1,0)
 
             process+="set /Herwig/UnderlyingEvent/MPIHandler:IdenticalToUE 0\n"
             if "-0" in parameterName   : process+=addFirstJet("0")
             elif "-1" in parameterName : process+=addFirstJet("5")
             elif "-2" in parameterName : process+=addFirstJet("15")
             elif "-3" in parameterName : process+=addFirstJet("20")
             elif "-4" in parameterName : process+=addFirstJet("50")
             elif "-5" in parameterName : process+=addFirstJet("80")
             elif "-6" in parameterName : process+=addFirstJet("110")
             elif "-7" in parameterName :
                 process+=addFirstJet("30")
                 process+=addSecondJet("25")
                 process+=addJetPairCut("90")
             elif "-8" in parameterName :
                 process+=addFirstJet("30")
                 process+=addSecondJet("25")
                 process+=addJetPairCut("340")
             elif "-9" in parameterName :
                 process+=addFirstJet("30")
                 process+=addSecondJet("25")
                 process+=addJetPairCut("500")
             else :
                 logging.error("Exit 00004")
                 sys.exit(1)
                   
         elif "Top-L" in parameterName :
             process+=setHardProcessWidthToZero(["t","tbar"])
             if(simulation=="Matchbox"):
                 process+=addProcess(thefactory,"p p t tbar","2","0","TopPairMTScale",0,0)
             elif(simulation=="Merging"):
                 process+=addProcess(thefactory,"p p t tbar","2","0","TopPairMTScale",2,2)
             process+=selectDecayMode("t",["t->nu_e,e+,b;",
                                           "t->nu_mu,mu+,b;"])
             process+=addBRReweighter()
             
         elif "Top-SL" in parameterName :
             process+=setHardProcessWidthToZero(["t","tbar"])
             if(simulation=="Matchbox"):
                 process+=addProcess(thefactory,"p p t tbar","2","0","TopPairMTScale",0,0)
             elif(simulation=="Merging"):
                 process+=addProcess(thefactory,"p p t tbar","2","0","TopPairMTScale",2,2)
             process+="set /Herwig/Particles/t:Synchronized Not_synchronized\n"
             process+="set /Herwig/Particles/tbar:Synchronized Not_synchronized\n"
             process+=selectDecayMode("t",["t->nu_e,e+,b;",
                                           "t->nu_mu,mu+,b;"])
             process+=selectDecayMode("tbar",["tbar->b,bbar,cbar;",
                                              "tbar->bbar,cbar,d;",
                                              "tbar->bbar,cbar,s;",
                                              "tbar->bbar,s,ubar;",
                                              "tbar->bbar,ubar,d;"])
             process+=addBRReweighter()
             
         elif "Top-All" in parameterName :
             process+=setHardProcessWidthToZero(["t","tbar"])
             if(simulation=="Matchbox"):
                 process+=addProcess(thefactory,"p p t tbar","2","0","TopPairMTScale",0,0)
             elif(simulation=="Merging"):
                 process+=addProcess(thefactory,"p p t tbar","2","0","TopPairMTScale",2,2)
         elif "WZ" in parameterName :
             if(simulation=="Merging"):
               logging.warning("WZ not explicitly tested for %s " % simulation)
               sys.exit(0)
             process+=setHardProcessWidthToZero(["W+","W-","Z0"])
             process+=addProcess(thefactory,"p p W+ Z0","0","2","FixedScale",0,0)
             process+=addProcess(thefactory,"p p W- Z0","0","2","FixedScale",0,0)
             process+="set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 171.6*GeV\n\n"
             process+=selectDecayMode("W+",["W+->nu_e,e+;",
                                            "W+->nu_mu,mu+;"])
             process+=selectDecayMode("W-",["W-->nu_ebar,e-;",
                                            "W-->nu_mubar,mu-;"])
             process+=selectDecayMode("Z0",["Z0->e-,e+;",
                                            "Z0->mu-,mu+;"])
             process+=addBRReweighter()
             process+=addLeptonPairCut("60","120")
         elif "WW-emu" in parameterName :
             if(simulation=="Merging"):
               logging.warning("WW-emu not explicitly tested for %s " % simulation)
               sys.exit(0)
             
             process+=setHardProcessWidthToZero(["W+","W-","Z0"])
             process+=addProcess(thefactory,"p p W+ W-","0","2","FixedScale",0,0)
             process+="set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 160.8*GeV\n"
             process+="set /Herwig/Particles/W+:Synchronized 0\n"
             process+="set /Herwig/Particles/W-:Synchronized 0\n"
             process+=selectDecayMode("W+",["W+->nu_e,e+;"])
             process+=selectDecayMode("W-",["W-->nu_mubar,mu-;"])
             process+=addBRReweighter()
             parameters["bscheme"] = "read Matchbox/FourFlavourScheme.in\n"
             
             process+=addLeptonPairCut("60","120")
         elif "WW-ll" in parameterName :
             if(simulation=="Merging"):
               logging.warning("WW-ll not explicitly tested for %s " % simulation)
               sys.exit(0)
             process+=setHardProcessWidthToZero(["W+","W-","Z0"])
             process+=addProcess(thefactory,"p p W+ W-","0","2","FixedScale",0,0)
             process+="set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 160.8*GeV\n"
             process+=selectDecayMode("W+",["W+->nu_e,e+;",
                                            "W+->nu_mu,mu+;",
                                            "W+->nu_tau,tau+;"])
             process+=addBRReweighter()
             process+=addLeptonPairCut("60","120")
             parameters["bscheme"] = "read Matchbox/FourFlavourScheme.in\n"
 
         elif "ZZ-ll" in parameterName :
             if(simulation=="Merging"):
               logging.warning("ZZ-ll not explicitly tested for %s " % simulation)
               sys.exit(0)
             process+=setHardProcessWidthToZero(["W+","W-","Z0"])
             process+=addProcess(thefactory,"p p Z0 Z0","0","2","FixedScale",0,0)
             process+="set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 182.2*GeV\n"
             process+=selectDecayMode("Z0",["Z0->e-,e+;",
                                            "Z0->mu-,mu+;",
                                            "Z0->tau-,tau+;"])
             process+=addBRReweighter()
             process+=addLeptonPairCut("60","120")
         elif "ZZ-lv" in parameterName :
             if(simulation=="Merging"):
               logging.warning("ZZ-lv not explicitly tested for %s " % simulation)
               sys.exit(0)
             process+=setHardProcessWidthToZero(["W+","W-","Z0"])
             process+=addProcess(thefactory,"p p Z0 Z0","0","2","FixedScale",0,0)
             process+="set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 182.2*GeV\n"
             process+=selectDecayMode("Z0",["Z0->e-,e+;",
                                            "Z0->mu-,mu+;",
                                            "Z0->tau-,tau+;",
                                            "Z0->nu_e,nu_ebar;",
                                            "Z0->nu_mu,nu_mubar;",
                                            "Z0->nu_tau,nu_taubar;"])
             process+=addBRReweighter()
             process+=addLeptonPairCut("60","120")
         elif "W-e" in parameterName :
             if(simulation=="Matchbox"):
                 process+=addProcess(thefactory,"p p e+ nu","0","2","LeptonPairMassScale",0,0)
                 process+=addProcess(thefactory,"p p e- nu","0","2","LeptonPairMassScale",0,0)
             elif(simulation=="Merging"):
                 process+=particlegroup(thefactory,'epm','e+','e-')
                 process+=addProcess(thefactory,"p p epm nu","0","2","LeptonPairMassScale",2,2)
             process+=addLeptonPairCut("60","120")
 
         elif "W-mu" in parameterName :
             if(simulation=="Matchbox"):
                 process+=addProcess(thefactory,"p p mu+ nu","0","2","LeptonPairMassScale",0,0)
                 process+=addProcess(thefactory,"p p mu- nu","0","2","LeptonPairMassScale",0,0)
             elif(simulation=="Merging"):
                 process+=particlegroup(thefactory,'mupm','mu+','mu-')
                 process+=addProcess(thefactory,"p p mupm nu","0","2","LeptonPairMassScale",2,2)
             process+=addLeptonPairCut("60","120")
         elif "Z-e" in parameterName or "Z-mu" in parameterName :
             if "Z-e" in parameterName :
                 if(simulation=="Matchbox"):
                     process+=addProcess(thefactory,"p p e+ e-","0","2","LeptonPairMassScale",0,0)
                 elif(simulation=="Merging"):
                     process+=addProcess(thefactory,"p p e+ e-","0","2","LeptonPairMassScale",2,2)
             elif "Z-mu" in parameterName :
                 if(simulation=="Matchbox"):
                     process+=addProcess(thefactory,"p p mu+ mu-","0","2","LeptonPairMassScale",0,0)
                 elif(simulation=="Merging"):
                     process+=addProcess(thefactory,"p p mu+ mu-","0","2","LeptonPairMassScale",2,2)
             mcuts=[10,35,75,110,400,ecms]
             for i in range(1,6) :
                 tstring = "-Mass%s"%i
                 if tstring in parameterName :
                     process+=addLeptonPairCut(mcuts[i-1],mcuts[i])
                     parameterName=parameterName.replace(tstring,"")
         elif "Z-nu" in parameterName :
             if(simulation=="Matchbox"):
                 process+=addProcess(thefactory,"p p nu nu","0","2","LeptonPairMassScale",0,0)
             elif(simulation=="Merging"):
                 process+=addProcess(thefactory,"p p nu nu","0","2","LeptonPairMassScale",2,2)
         elif "Z-jj" in parameterName :
             if(simulation=="Merging"):
               logging.warning("Z-jj not explicitly tested for %s " % simulation)
               sys.exit(0)
             process+=addProcess(thefactory,"p p e+ e- j j","2","2","LeptonPairMassScale",0,0)
             process+=addFirstJet("40")
             process+=addSecondJet("30")
             process+=addLeptonPairCut("60","120")
         elif "W-Jet" in parameterName :
             if(simulation=="Merging"):
               logging.warning("W-Jet not explicitly tested for %s " % simulation)
               sys.exit(0)
             
             process+=addProcess(thefactory,"p p e+ nu j","1","2","HTScale",0,0)
             process+=addProcess(thefactory,"p p e- nu j","1","2","HTScale",0,0)
             
             process+=addLeptonPairCut("60","120")
             if "W-Jet-1-e" in parameterName :
                 process+=addFirstJet("100")
                 parameterName=parameterName.replace("W-Jet-1-e","W-Jet-e")
             elif "W-Jet-2-e" in parameterName :
                 process+=addFirstJet("190")
                 parameterName=parameterName.replace("W-Jet-2-e","W-Jet-e")
             elif "W-Jet-3-e" in parameterName :
                 process+=addFirstJet("270")
                 parameterName=parameterName.replace("W-Jet-3-e","W-Jet-e")
             else :
                 logging.error("Exit 00005")
                 sys.exit(1)
         elif "Z-Jet" in parameterName :
             if(simulation=="Merging"):
               logging.warning("Z-Jet not explicitly tested for %s " % simulation)
               sys.exit(0)
             
             
             if "-e" in parameterName :
                 process+=addProcess(thefactory,"p p e+ e- j","1","2","HTScale",0,0)
                 if "Z-Jet-0-e" in parameterName :
                     process+=addFirstJet("35")
                     parameterName=parameterName.replace("Z-Jet-0-e","Z-Jet-e")
                 elif "Z-Jet-1-e" in parameterName :
                     process+=addFirstJet("100")
                     parameterName=parameterName.replace("Z-Jet-1-e","Z-Jet-e")
                 elif "Z-Jet-2-e" in parameterName :
                     process+=addFirstJet("190")
                     parameterName=parameterName.replace("Z-Jet-2-e","Z-Jet-e")
                 elif "Z-Jet-3-e" in parameterName :
                     process+=addFirstJet("270")
                     parameterName=parameterName.replace("Z-Jet-3-e","Z-Jet-e")
                 else :
                     logging.error("Exit 00006")
                     sys.exit(1)
             else :
                 process+=addProcess(thefactory,"p p mu+ mu- j","1","2","HTScale",0,0)
                 process+=addFirstJet("35")
                 parameterName=parameterName.replace("Z-Jet-0-mu","Z-Jet-mu")
             process+=addLeptonPairCut("60","120")
         elif "Z-bb" in parameterName :
             if(simulation=="Merging"):
               logging.warning("Z-bb not explicitly tested for %s " % simulation)
               sys.exit(0)
             parameters["bscheme"]=fourFlavour
             process+="set /Herwig/Particles/b:HardProcessMass 4.2*GeV\nset /Herwig/Particles/bbar:HardProcessMass 4.2*GeV\n"
             process+=addProcess(thefactory,"p p e+ e- b bbar","2","2","FixedScale",0,0)
             process+=addLeptonPairCut("66","116")
             process+=addFirstJet("18")
             process+=addSecondJet("15")
             process+=addLeptonPairCut("60","120")
         elif "Z-b" in parameterName :
             if(simulation=="Merging"):
               logging.warning("Z-b not explicitly tested for %s " % simulation)
               sys.exit(0)
             process+=particlegroup(thefactory,'bjet','b','bbar')
             process+=addProcess(thefactory,"p p e+ e- bjet","1","2","FixedScale",0,0)
             process+="set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 91.2*GeV\n"
             process+=addLeptonPairCut("60","120")
             process+=addFirstJet("15")
         elif "W-b" in parameterName :
             if(simulation=="Merging"):
               logging.warning("W-b not explicitly tested for %s " % simulation)
               sys.exit(0)
             parameters["bscheme"]=fourFlavour
             process += "set /Herwig/Particles/b:HardProcessMass 4.2*GeV\nset /Herwig/Particles/bbar:HardProcessMass 4.2*GeV\n"
             process+=addProcess(thefactory,"p p e-  nu b bbar","2","2","FixedScale",0,0)
             process+=addProcess(thefactory,"p p mu+ nu b bbar","2","2","FixedScale",0,0)
             process += "set /Herwig/MatrixElements/Matchbox/Scales/FixedScale:FixedScale 80.4*GeV\n"
             process+=addFirstJet("30")
             process+=addLeptonPairCut("60","120")
         else :
             logging.error(" Process %s not supported for Matchbox matrix elements" % name)
             sys.exit(1)
 # LHC-GammaGamma
 elif(collider=="LHC-GammaGamma" ) :
     if   "-7-" in parameterName : process = StringBuilder(collider_lumi(7000.0))
     elif "-8-" in parameterName : process = StringBuilder(collider_lumi(8000.0))
     else :                        process = StringBuilder(collider_lumi(7000.0))
     if(simulation=="") :
         if "7" in parameterName : process += insert_ME("MEgg2ff","Muon")
         else :
             logging.error(" Process %s not supported for default matrix elements" % name)
             sys.exit(1)
     else :
         logging.error("LHC-GammaGamma not supported for %s " % simulation)
         sys.exit(1)
 
 if "EHS" in name :
     pFile = os.path.join(collider,"{c}-{pn}.in".format(c="EHS", pn=parameterName))
 else :
     pFile = os.path.join(collider,"{c}-{pn}.in".format(c=collider, pn=parameterName))
 with open(os.path.join("Rivet",pFile), 'r') as f:
     parameters['parameterFile'] = f.read()
     
 parameters['runname'] = 'Rivet-%s' % name
 parameters['process'] = str(process)
 if have_hadronic_collider :
     if "EHS" in name :
         parameters['collider'] = "PPCollider.in\nread snippets/FixedTarget-PP.in"
     else :
         parameters['collider'] = "PPCollider.in"
 
 #check if selecteddecaymode and addedBRReweighter is consistent
 
 if selecteddecaymode and not addedBRReweighter:
     logging.error("Decaymode was selected but no BRReweighter was added.")
     sys.exit(1)
 
 if addedBRReweighter and not selecteddecaymode:
     logging.error("BRReweighter was added but no Decaymode was selected.")
     sys.exit(1)
 
 # check that we only add one process if in merging mode:
 
 if numberOfAddedProcesses > 1 and simulation =="Merging":
     logging.error("In Merging only one process is allowed at the moment. See ticket #403.")
     sys.exit(1)
 
 # Check if a process was added for Merging or Matchbox:
 
 if numberOfAddedProcesses == 0 and (simulation =="Merging" or simulation =="Matchbox"):
     logging.error("No process was selected.")
     sys.exit(1)
 
 # get template and write the file
 with open(os.path.join("Rivet/Templates",templateName), 'r') as f:
     templateText = f.read()
 
 template = Template( templateText )
 
 with open(os.path.join("Rivet",name+".in"), 'w') as f:
         f.write( template.substitute(parameters) )
diff --git a/Tests/python/merge-EE-Gamma.in b/Tests/python/merge-EE-Gamma.in
--- a/Tests/python/merge-EE-Gamma.in
+++ b/Tests/python/merge-EE-Gamma.in
@@ -1,138 +1,140 @@
 #! @PYTHON@
 # -*- mode: python -*-
 from __future__ import print_function
 import logging,sys, os, yoda, copy
 
 if sys.version_info[:3] < (2,4,0):
     print ("rivet scripts require Python version >= 2.4.0... exiting")
     sys.exit(1)
 
 
 #############################################
 
 def fillAbove(desthisto, sourcehistosbysqrts):
     if type(desthisto) is yoda.core.Scatter2D :
         for sqrts in sorted(sourcehistosbysqrts.keys()) :
             h=sourcehistosbysqrts[sqrts]
             for i in range(0,h.numPoints()) :
                 if sqrts==h.points()[i].x() :
                     desthisto.addPoint(h.points()[i])
 
     elif(type(desthisto)==yoda.core.Profile1D) :
         for sqrts, h in sorted(sourcehistosbysqrts.items()) :
             for i in range(0,h.numBins()) :
                 if(sqrts>=h.bins()[i].xMin() and \
                    sqrts<=h.bins()[i].xMax()) :
                     desthisto.bins()[i] += h.bins()[i]
                     break
     else :
         logging.error("Unknown analysis object" + desthisto.path)
         sys.exit(1)
 
 def merge(hpath):
     global inhistos
     global outhistos
     try:
         fillAbove(outhistos[hpath], inhistos[hpath])
     except:
         pass
 
 def useOne(hpath, sqrts):
     global inhistos
     global outhistos
     try:
         outhistos[hpath] =  inhistos[hpath][float(sqrts)]
     except:
         pass
 
 if __name__ == "__main__":
     import logging
     from optparse import OptionParser, OptionGroup
     parser = OptionParser(usage="%prog name")
     verbgroup = OptionGroup(parser, "Verbosity control")
     verbgroup.add_option("-v", "--verbose", action="store_const", const=logging.DEBUG, dest="LOGLEVEL",
                          default=logging.INFO, help="print debug (very verbose) messages")
     verbgroup.add_option("-q", "--quiet", action="store_const", const=logging.WARNING, dest="LOGLEVEL",
                          default=logging.INFO, help="be very quiet")
     parser.add_option_group(verbgroup)
     (opts, args) = parser.parse_args()
     logging.basicConfig(level=opts.LOGLEVEL, format="%(message)s")
     ## Check args
     if len(args) < 1:
         logging.error("Must specify at least the name of the files")
         sys.exit(1)
 
 #######################################
 
 yodafiles=["-Direct-mumu-161","-Direct-mumu-172","-Direct-mumu-183",
            "-Direct-mumu-189","-Direct-mumu-196","-Direct-mumu-206",
            "-Direct-tautau-189","-Direct-tautau-196","-Direct-tautau-206",
            "-Direct-Jets-198","-Single-Resolved-Jets-198","-Double-Resolved-Jets-198",
-           "-Direct-Jets-206","-Single-Resolved-Jets-206","-Double-Resolved-Jets-206",]
+           "-Direct-Jets-206","-Single-Resolved-Jets-206","-Double-Resolved-Jets-206",
+           "-pi0-10.58","-Eta-10.58","-EtaPrime-10.58",
+           "-Eta-1","-Eta-29","-EtaPrime-34.3","-EtaPrime-91.2"]
 
 # Get histos
 inhistos  = {}
 outhistos = {}
 for f in yodafiles:
     file = "Rivet-%s%s.yoda" % (args[0], f)
     sqrts=float(f.split("-")[-1].replace(".yoda",""))
     if not os.access(file, os.R_OK):
         logging.error("%s cannot be read" % file)
         continue
     try:
         aos = yoda.read(file)
     except:
         logging.error("%s cannot be parsed as yoda" % file)
         continue
     ## Get histos from this YODA file
     for aopath, ao in aos.items() :
         if("RAW" in aopath or "_XSEC" in aopath or "_EVTCOUNT" in aopath ) :continue
         # merge of different energy values
-        if("L3_2004_I645127" in aopath) :
+        if "L3_2004_I645127" in aopath :
             if(("d01" in aopath and "mu" in file) or
                ("d02" in aopath and "tau" in file)) :
                 if aopath not in inhistos :
                     inhistos[aopath] = {}
                 if sqrts not in inhistos[aopath]:
                     inhistos[aopath][sqrts] = ao
                 else:
                     raise Exception("A set with sqrts = %s already exists" % ( sqrts))
         else :
             if(aopath in outhistos) :
                 outhistos[aopath] += ao
             else :
                 outhistos[aopath] = ao
 ## Make empty output histos if needed
 for hpath,hsets in inhistos.items():
     if("L3_2004_I645127" in hpath ) :
         histo = list(hsets.values())[0]
         if(type(histo)==yoda.core.Scatter2D) :
             outhistos[hpath] = yoda.core.Scatter2D(histo.path(),
                                                    histo.title())
         elif(type(histo)==yoda.core.Profile1D) :
             outhistos[hpath] = yoda.core.Profile1D(histo.path(),
                                                    histo.title())
             for i in range(0,histo.numBins) :
                 outhistos[hpath].addBin(histo.bins()[i].xMin(),
                                         histo.bins()[i].xMax())
         elif(type(histo)==yoda.core.Histo1D) :
             outhistos[hpath] = yoda.core.Histo1D(histo.path(),
                                                  histo.title())
             for i in range(0,histo.numBins) :
                 outhistos[hpath].addBin(histo.bins()[i].xMin(),
                                         histo.bins()[i].xMax())
         else :
             logging.error("Histogram %s is of unknown type" % hpath)
             sys.exit(1)
 
 merge("/L3_2004_I645127/d01-x01-y01")
 merge("/L3_2004_I645127/d01-x01-y02")
 merge("/L3_2004_I645127/d02-x01-y01")
 
 
 # Choose output file
 name = args[0]+".yoda"
 # output the yoda file
 print ("Write yoda to ",name)
 yoda.writeYODA(outhistos,name)
 sys.exit(0)
diff --git a/src/defaults/MatrixElements.in b/src/defaults/MatrixElements.in
--- a/src/defaults/MatrixElements.in
+++ b/src/defaults/MatrixElements.in
@@ -1,328 +1,354 @@
 # -*- ThePEG-repository -*-
 
 ##############################################################################
 # Setup of default matrix elements.
 #
 # Only one ME is activated by default, but this file lists 
 # some alternatives. All available MEs can be found in the
 # 'include/Herwig/MatrixElements' subdirectory of your Herwig 
 # installation.
 #
 # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # 
 #
 # Instead of editing this file directly, you should reset 
 # the matrix elements in your own input files:
 #
 # - create your custom SubProcessHandler
 # - insert the MEs you need
 # - set your SubProcessHandler instead of the default (see HerwigDefaults.in)
 ##############################################################################
 mkdir /Herwig/MatrixElements
 cd /Herwig/MatrixElements
 library HwMELepton.so
 library HwMEHadron.so
 library HwMEDIS.so
 
 ############################################################
 #  e+e- matrix elements
 ############################################################
 # e+e- > q qbar
 create Herwig::MEee2gZ2qq MEee2gZ2qq
 newdef MEee2gZ2qq:MinimumFlavour 1
 newdef MEee2gZ2qq:MaximumFlavour 5
 newdef MEee2gZ2qq:AlphaQCD /Herwig/Shower/AlphaQCDFSR
 newdef MEee2gZ2qq:AlphaQED /Herwig/Shower/AlphaQED
 
 # e+e- -> l+l-
 create Herwig::MEee2gZ2ll MEee2gZ2ll
 newdef MEee2gZ2ll:Allowed Charged
 set MEee2gZ2ll:AlphaQED /Herwig/Shower/AlphaQED
 
 # e+e- -> l+l-
 create Herwig::MEee2ff MEee2ff
 set MEee2ff:AlphaQED /Herwig/Shower/AlphaQED
 
 # e+e- -> W+W- ZZ
 create Herwig::MEee2VV MEee2VV
 
 # e+e- -> ZH
 create Herwig::MEee2ZH MEee2ZH
 newdef MEee2ZH:Coupling /Herwig/Shower/AlphaQCDFSR
 
 # e+e- -> e+e-H/nu_enu_ebarH
 create Herwig::MEee2HiggsVBF MEee2HiggsVBF
 
 
 ############################################################
 #  Low energy matrix elements
 ############################################################
 # e+ e- -> pi+pi-
 create Herwig::MEee2Mesons MEee2Pions HwMELeptonLowEnergy.so
 create Herwig::TwoPionCzyzCurrent /Herwig/Decays/TwoPionCzyzCurrent HwWeakCurrents.so
 set MEee2Pions:WeakCurrent /Herwig/Decays/TwoPionCzyzCurrent
 # e+ e- -> K+K-/ K0K0
 create Herwig::MEee2Mesons MEee2Kaons HwMELeptonLowEnergy.so
 create Herwig::TwoKaonCzyzCurrent /Herwig/Decays/TwoKaonCzyzCurrent 
 set MEee2Kaons:WeakCurrent /Herwig/Decays/TwoKaonCzyzCurrent
 # e+ e- -> pi+ pi- pi0
 create Herwig::MEee2Mesons MEee3Pions HwMELeptonLowEnergy.so
 create Herwig::ThreePionCzyzCurrent /Herwig/Decays/ThreePionCzyzCurrent
 set MEee3Pions:WeakCurrent /Herwig/Decays/ThreePionCzyzCurrent
 # e+ e- -> 2pi+ 2pi-, 2pi0, pi+ pi-
 create Herwig::MEee2Mesons MEee4Pions HwMELeptonLowEnergy.so
 create Herwig::FourPionCzyzCurrent /Herwig/Decays/FourPionCzyzCurrent
 set MEee4Pions:WeakCurrent /Herwig/Decays/FourPionCzyzCurrent
 # e+ e- -> eta pi+ pi-
 create Herwig::MEee2Mesons MEee2EtaPiPi HwMELeptonLowEnergy.so
 create Herwig::EtaPiPiCurrent /Herwig/Decays/EtaPiPiCurrent 
 set MEee2EtaPiPi:WeakCurrent /Herwig/Decays/EtaPiPiCurrent
 # e+ e- -> eta' pi+ pi-
 create Herwig::MEee2Mesons MEee2EtaPrimePiPi HwMELeptonLowEnergy.so
 create Herwig::EtaPrimePiPiCurrent /Herwig/Decays/EtaPrimePiPiCurrent 
 set MEee2EtaPrimePiPi:WeakCurrent /Herwig/Decays/EtaPrimePiPiCurrent
 # e+ e- -> omega pi (omega -> pi0 gamma)
 create Herwig::MEee2Mesons MEee2OmegaPi HwMELeptonLowEnergy.so
 create Herwig::TwoPionPhotonSNDCurrent /Herwig/Decays/OmegaPiCurrent 
 set MEee2OmegaPi:WeakCurrent /Herwig/Decays/OmegaPiCurrent
 # e+ e- > pi0 gamma
 create Herwig::MEee2Mesons MEee2PiGamma HwMELeptonLowEnergy.so
 create Herwig::PionPhotonCurrent /Herwig/Decays/PiGammaCurrent
 set MEee2PiGamma:WeakCurrent /Herwig/Decays/PiGammaCurrent
 # e+e- -> eta gamma
 create Herwig::MEee2Mesons MEee2EtaGamma HwMELeptonLowEnergy.so
 create Herwig::EtaPhotonCurrent /Herwig/Decays/EtaGammaCurrent
 set MEee2EtaGamma:WeakCurrent /Herwig/Decays/EtaGammaCurrent
 # e+e- -> eta phi
 create Herwig::MEee2Mesons MEee2EtaPhi HwMELeptonLowEnergy.so
 create Herwig::EtaPhiCurrent /Herwig/Decays/EtaPhiCurrent
 set MEee2EtaPhi:WeakCurrent /Herwig/Decays/EtaPhiCurrent
 # e+e- -> eta omega
 create Herwig::MEee2Mesons MEee2EtaOmega HwMELeptonLowEnergy.so
 create Herwig::EtaOmegaCurrent /Herwig/Decays/EtaOmegaCurrent
 set MEee2EtaOmega:WeakCurrent /Herwig/Decays/EtaOmegaCurrent
 # e+e- > p pbar
 create Herwig::MEee2Mesons MEee2PPbar HwMELeptonLowEnergy.so
 create Herwig::WeakBaryonCurrent  /Herwig/Decays/CzyzCurrent
 create Herwig::CzyzNucleonFormFactor  /Herwig/Decays/CzyzFormFactor HwFormFactors.so
 set /Herwig/Decays/CzyzCurrent:FormFactor /Herwig/Decays/CzyzFormFactor
 set MEee2PPbar:WeakCurrent /Herwig/Decays/CzyzCurrent
 # e+e- > hyperons
 create Herwig::MEee2Mesons MEee2LL HwMELeptonLowEnergy.so
 create Herwig::WeakBaryonCurrent  /Herwig/Decays/KornerKurodaCurrent
 create Herwig::KornerKurodaFormFactor  /Herwig/Decays/KornerKurodaFormFactor
 set /Herwig/Decays/KornerKurodaFormFactor:IncludeNucleon No
 set /Herwig/Decays/KornerKurodaCurrent:FormFactor /Herwig/Decays/KornerKurodaFormFactor
 set MEee2LL:WeakCurrent /Herwig/Decays/KornerKurodaCurrent
 # e+e- -> KKpi
 create Herwig::MEee2Mesons MEee2KKPi HwMELeptonLowEnergy.so
 create Herwig::KKPiCurrent /Herwig/Decays/KKPiCurrent 
 set MEee2KKPi:WeakCurrent /Herwig/Decays/KKPiCurrent
 # e+e- -> phi pi
 create Herwig::MEee2Mesons MEee2PhiPi HwMELeptonLowEnergy.so
 create Herwig::PhiPiCurrent /Herwig/Decays/PhiPiCurrent 
 set MEee2PhiPi:WeakCurrent /Herwig/Decays/PhiPiCurrent
 # e+ e- -> omega pi pi 
 create Herwig::MEee2Mesons MEee2OmegaPiPi HwMELeptonLowEnergy.so
 create Herwig::OmegaPiPiCurrent /Herwig/Decays/OmegaPiPiCurrent 
 set MEee2OmegaPiPi:WeakCurrent /Herwig/Decays/OmegaPiPiCurrent
 
 ############################################################
 # NLO (POWHEG e+e- matrix elements
 ############################################################
 library HwPowhegMELepton.so 
 create Herwig::MEee2gZ2qqPowheg PowhegMEee2gZ2qq
 newdef PowhegMEee2gZ2qq:MinimumFlavour 1
 newdef PowhegMEee2gZ2qq:MaximumFlavour 5
 newdef PowhegMEee2gZ2qq:AlphaQCD /Herwig/Shower/AlphaQCDFSR
 newdef PowhegMEee2gZ2qq:AlphaQED /Herwig/Shower/AlphaQED
 create Herwig::MEee2gZ2llPowheg PowhegMEee2gZ2ll
 newdef PowhegMEee2gZ2ll:Allowed Charged
 set PowhegMEee2gZ2ll:AlphaQED /Herwig/Shower/AlphaQED
 
 ############################################################
 #  hadron-hadron matrix elements
 ############################################################
 
 ###################################
 #  Electroweak processes
 ###################################
 # q qbar -> gamma/Z -> l+l-
 create Herwig::MEqq2gZ2ff MEqq2gZ2ff
 newdef MEqq2gZ2ff:Process 3
 newdef MEqq2gZ2ff:Coupling /Herwig/Shower/AlphaQCDISR
 
 # q qbar to W -> l nu
 create Herwig::MEqq2W2ff  MEqq2W2ff
 newdef MEqq2W2ff:Process 2
 newdef MEqq2W2ff:Coupling /Herwig/Shower/AlphaQCDISR
 
 # W+jet
 create Herwig::MEPP2WJet MEWJet
 newdef MEWJet:WDecay Leptons
 
 # Z+jet
 create Herwig::MEPP2ZJet MEZJet
 newdef MEZJet:ZDecay ChargedLeptons
 
 # PP->WW/WZ/ZZ
 create Herwig::MEPP2VV MEPP2VV
 
 # PP->WZ gamma
 create Herwig::MEPP2VGamma MEPP2VGamma
 
 ###################################
 #  Photon and jet processes
 ###################################
 
 # qqbar/gg -> gamma gamma
 create Herwig::MEPP2GammaGamma MEGammaGamma
 
 # hadron-hadron to gamma+jet
 create Herwig::MEPP2GammaJet   MEGammaJet
 
 # QCD 2-to-2
 create Herwig::MEQCD2to2       MEQCD2to2
 
 # MinBias
 create Herwig::MEMinBias MEMinBias
 newdef MEMinBias:csNorm 0.01
 newdef MEMinBias:Scale 2.0
 ###################################
 #  Heavy Quark
 ###################################
 
 # qqbar/gg -> t tbar
 create Herwig::MEPP2QQ         MEHeavyQuark     
 
 create Herwig::MEPP2SingleTop MESingleTopTChannel
 set MESingleTopTChannel:Process tChannel
 
 create Herwig::MEPP2SingleTop MESingleTopSChannel
 set MESingleTopSChannel:Process sChannel
 
 create Herwig::MEPP2SingleTop MESingleTopTW
 set MESingleTopTW:Process tW
 
 ###################################
 #  Higgs processes
 ###################################
 
 # hadron-hadron to higgs
 create Herwig::MEPP2Higgs   MEHiggs
 newdef MEHiggs:ShapeScheme MassGenerator
 newdef MEHiggs:Process gg
 newdef MEHiggs:Coupling /Herwig/Shower/AlphaQCDISR
 
 # hadron-hadron to higgs+jet
 create Herwig::MEPP2HiggsJet   MEHiggsJet
 
 # PP->ZH
 create Herwig::MEPP2ZH MEPP2ZH
 newdef MEPP2ZH:Coupling /Herwig/Shower/AlphaQCDISR
 
 # PP->WH
 create Herwig::MEPP2WH MEPP2WH
 newdef MEPP2WH:Coupling /Herwig/Shower/AlphaQCDISR
 
 # PP -> Higgs via VBF
 create Herwig::MEPP2HiggsVBF MEPP2HiggsVBF
 newdef MEPP2HiggsVBF:ShowerAlphaQCD /Herwig/Shower/AlphaQCDISR
 
 # PP -> t tbar Higgs
 create Herwig::MEPP2QQHiggs MEPP2ttbarH
 newdef MEPP2ttbarH:QuarkType Top
 
 # PP -> b bbar Higgs
 create Herwig::MEPP2QQHiggs MEPP2bbbarH
 newdef MEPP2bbbarH:QuarkType Bottom
 
 ##########################################################
 # Hadron-Hadron NLO matrix elements in the Powheg scheme
 ##########################################################
 library HwPowhegMEHadron.so
 
 # q qbar -> gamma/Z -> l+l-
 create Herwig::MEqq2gZ2ffPowheg PowhegMEqq2gZ2ff
 newdef PowhegMEqq2gZ2ff:Process 3
 newdef PowhegMEqq2gZ2ff:Coupling /Herwig/Shower/AlphaQCDISR
 
 # q qbar to W -> l nu
 create Herwig::MEqq2W2ffPowheg PowhegMEqq2W2ff
 newdef PowhegMEqq2W2ff:Process 2
 newdef PowhegMEqq2W2ff:Coupling /Herwig/Shower/AlphaQCDISR
  
 # PP->ZH
 create Herwig::MEPP2ZHPowheg PowhegMEPP2ZH
 newdef PowhegMEPP2ZH:Coupling /Herwig/Shower/AlphaQCDISR
 
 # PP->WH
 create Herwig::MEPP2WHPowheg PowhegMEPP2WH
 newdef PowhegMEPP2WH:Coupling /Herwig/Shower/AlphaQCDISR
 
 # hadron-hadron to higgs
 create Herwig::MEPP2HiggsPowheg PowhegMEHiggs
 newdef PowhegMEHiggs:ShapeScheme MassGenerator
 newdef PowhegMEHiggs:Process gg
 newdef PowhegMEHiggs:Coupling /Herwig/Shower/AlphaQCDISR
 
 # PP->VV
 create Herwig::MEPP2VVPowheg PowhegMEPP2VV
 newdef PowhegMEPP2VV:Coupling /Herwig/Shower/AlphaQCDISR
 
 # PP -> Higgs via VBF
 create Herwig::MEPP2HiggsVBFPowheg PowhegMEPP2HiggsVBF
 newdef PowhegMEPP2HiggsVBF:ShowerAlphaQCD /Herwig/Shower/AlphaQCDISR
 
 # PP -> diphoton NLO
 create Herwig::MEPP2GammaGammaPowheg MEGammaGammaPowheg 
 set MEGammaGammaPowheg:Process 0
 set MEGammaGammaPowheg:Contribution 1
 set MEGammaGammaPowheg:ShowerAlphaQCD /Herwig/Shower/AlphaQCDISR
 set MEGammaGammaPowheg:ShowerAlphaQED /Herwig/Shower/AlphaQED
 
 ##########################################################
 # DIS matrix elements
 ##########################################################
 
 # neutral current
 create Herwig::MENeutralCurrentDIS MEDISNC
 newdef MEDISNC:Coupling /Herwig/Shower/AlphaQCDISR
 newdef MEDISNC:Contribution 0
 # charged current
 create Herwig::MEChargedCurrentDIS MEDISCC
 newdef MEDISCC:Coupling /Herwig/Shower/AlphaQCDISR
 newdef MEDISCC:Contribution 0
 
 # neutral current (POWHEG)
 create Herwig::MENeutralCurrentDIS PowhegMEDISNC
 newdef PowhegMEDISNC:Coupling /Herwig/Shower/AlphaQCDISR
 newdef PowhegMEDISNC:Contribution 1
 # charged current (POWHEG)
 create Herwig::MEChargedCurrentDIS PowhegMEDISCC
 newdef PowhegMEDISCC:Coupling /Herwig/Shower/AlphaQCDISR
 newdef PowhegMEDISCC:Contribution 1
 
 ##########################################################
 # Gamma-Gamma matrix elements
 ##########################################################
 
 # fermion-antiferimon
-create Herwig::MEGammaGamma2ff MEgg2ff HwMEGammaGamma.so
+create Herwig::MEGammaGamma2X MEgg2ff HwMEGammaGamma.so
+create Herwig::GammaGamma2ffAmplitude gg2ffAmp
+newdef MEgg2ff:Amplitude gg2ffAmp
 
 # W+ W-
 create Herwig::MEGammaGamma2WW MEgg2WW HwMEGammaGamma.so
 
+# f f -> f f pi0,eta,eta' via 2 photon process
+# pi0
+create Herwig::MEff2ffX MEff2ffpi0
+create Herwig::GammaGamma2PseudoScalarAmplitude AmpGG2pi0
+newdef MEff2ffpi0:Amplitude AmpGG2pi0
+set AmpGG2pi0:FTT 0.274
+set AmpGG2pi0:LambdaP2 0.6
+set AmpGG2pi0:Particle /Herwig/Particles/pi0
+# eta
+create Herwig::MEff2ffX MEff2ffeta
+create Herwig::GammaGamma2PseudoScalarAmplitude AmpGG2eta
+newdef MEff2ffeta:Amplitude AmpGG2eta
+set AmpGG2eta:FTT 0.274
+set AmpGG2eta:LambdaP2 0.6
+set AmpGG2eta:Particle /Herwig/Particles/eta
+# eta'
+create Herwig::MEff2ffX MEff2ffetaPrime
+create Herwig::GammaGamma2PseudoScalarAmplitude AmpGG2etaPrime
+set AmpGG2etaPrime:Particle /Herwig/Particles/eta'
+set AmpGG2etaPrime:FTT 0.344
+set AmpGG2etaPrime:LambdaP2 0.6
+set AmpGG2etaPrime:MassOption OffShell
+newdef MEff2ffetaPrime:Amplitude AmpGG2etaPrime
+
 ##########################################################
 # Gamma-Hadron matrix elements
 ##########################################################
 
 # gamma parton -> 2 jets
 create Herwig::MEGammaP2Jets MEGammaP2Jets HwMEGammaHadron.so
 
 ##########################################################
 # Set up the Subprocesses
 #
 # Generic for all colliders
 ##########################################################
 create ThePEG::SubProcessHandler SubProcess
 newdef SubProcess:PartonExtractor /Herwig/Partons/PPExtractor