diff --git a/Hadronization/MatrixElementClusterFissioner.cc b/Hadronization/MatrixElementClusterFissioner.cc
--- a/Hadronization/MatrixElementClusterFissioner.cc
+++ b/Hadronization/MatrixElementClusterFissioner.cc
@@ -1,2084 +1,2090 @@
 // -*- C++ -*-
 //
 // MatrixElementClusterFissioner.cc is a part of Herwig - A multi-purpose Monte Carlo event generator
 // Copyright (C) 2002-2019 The Herwig Collaboration
 //
 // Herwig is licenced under version 3 of the GPL, see COPYING for details.
 // Please respect the MCnet academic guidelines, see GUIDELINES for details.
 //
 //
 // Thisk is the implementation of the non-inlined, non-templated member
 // functions of the MatrixElementClusterFissioner class.
 //
 
 #include "MatrixElementClusterFissioner.h"
 #include <ThePEG/Interface/ClassDocumentation.h>
 #include <ThePEG/Interface/Reference.h>
 #include <ThePEG/Interface/Parameter.h>
 #include <ThePEG/Interface/Switch.h>
 #include <ThePEG/Persistency/PersistentOStream.h>
 #include <ThePEG/Persistency/PersistentIStream.h>
 #include <ThePEG/PDT/EnumParticles.h>
 #include "Herwig/Utilities/Kinematics.h"
 #include "Cluster.h"
 #include "ThePEG/Repository/UseRandom.h"
 #include "ThePEG/Repository/EventGenerator.h"
 #include <ThePEG/Utilities/DescribeClass.h>
 #include "ThePEG/Interface/ParMap.h"
 
 #include "Herwig/Utilities/AlphaS.h"
 
 #include <boost/numeric/ublas/matrix.hpp>
 #include <boost/numeric/ublas/io.hpp>
 #include <boost/numeric/ublas/lu.hpp>
 #include <cassert>
 #include <vector>
 using namespace Herwig;
 
 DescribeClass<MatrixElementClusterFissioner,ClusterFissioner>
 describeMatrixElementClusterFissioner("Herwig::MatrixElementClusterFissioner","Herwig.so");
 
 // Initialize counters
 unsigned int MatrixElementClusterFissioner::_counterMaxLoopViolations=0;
 unsigned int MatrixElementClusterFissioner::_counterPaccGreater1=0;
 unsigned int MatrixElementClusterFissioner::_counterFissionMatrixElement=0;
 MatrixElementClusterFissioner::MatrixElementClusterFissioner() :
   _allowHadronFinalStates(2),
   _massSampler(0),
   _phaseSpaceSamplerCluster(0),
   _phaseSpaceSamplerConstituent(0),
   _matrixElement(0),
 	_fissionApproach(0),
 	_powerLawPower(0.0),
 	_maxLoopFissionMatrixElement(5000000),
 	_safetyFactorMatrixElement(10.0),
 	_epsilonResolution(1.0),
 	_failModeMaxLoopMatrixElement(0),
 	_writeOut(0)
 {}
 
 MatrixElementClusterFissioner::~MatrixElementClusterFissioner(){
 	if (_counterMaxLoopViolations){
 		std::cout << "WARNING: There have been "
 			<< _counterMaxLoopViolations
 			<< "/" << _counterFissionMatrixElement
 			<< " Maximum tries violations during the Simulation! ("
 			<< 100.0*double(_counterMaxLoopViolations)/double(_counterFissionMatrixElement)
 			<< " %)\n"
 			<< "You may want to reduce MatrixElementClusterFissioner:SafetyFactorOverEst (=>potentially Pacc>=1) "
 			<< "and/or increase MatrixElementClusterFissioner:MaxLoopMatrixElement (=>slower performance)\n";
 	}
 	if (_counterPaccGreater1){
 		std::cout << "WARNING: There have been "
 			<< _counterPaccGreater1
 			<< "/" << _counterFissionMatrixElement
 			<< " Pacc>=1 exceptions during the Simulation! ("
 			<< 100.0*double(_counterPaccGreater1)/double(_counterFissionMatrixElement)
 			<< " %)\n"
 			<< "You may want to increase MatrixElementClusterFissioner:SafetyFactorOverEst to reduce this "
 			<< "\nNOTE: look at the log file and look for the larges Pacc accepted and multiply "
 			<< "\n      MatrixElementClusterFissioner:SafetyFactorOverEst by this factor";
 	}
 }
 IBPtr MatrixElementClusterFissioner::clone() const {
   return new_ptr(*this);
 }
 
 IBPtr MatrixElementClusterFissioner::fullclone() const {
   return new_ptr(*this);
 }
 
 void MatrixElementClusterFissioner::persistentOutput(PersistentOStream & os) const {
   os << _allowHadronFinalStates
 	 << _massSampler
 	 << _phaseSpaceSamplerCluster
 	 << _phaseSpaceSamplerConstituent
 	 << _matrixElement
 	 << _fissionApproach
 	 << _powerLawPower
 	 << _maxLoopFissionMatrixElement
 	 << _safetyFactorMatrixElement
 	 << _epsilonResolution
 	 << _failModeMaxLoopMatrixElement
 	 << _writeOut
 	 ;
 }
 void MatrixElementClusterFissioner::persistentInput(PersistentIStream & is, int) {
   is >> _allowHadronFinalStates
 	 >> _massSampler
 	 >> _phaseSpaceSamplerCluster
 	 >> _phaseSpaceSamplerConstituent
 	 >> _matrixElement
 	 >> _fissionApproach
 	 >> _powerLawPower
 	 >> _maxLoopFissionMatrixElement
 	 >> _safetyFactorMatrixElement
 	 >> _epsilonResolution
 	 >> _failModeMaxLoopMatrixElement
 	 >> _writeOut
 	 ;
 }
 /*
 namespace{
 	void printV(Lorentz5Momentum p) {
 		std::cout << "("<<p.e()/GeV<<"|"<<p.vect().x()/GeV<<","<<p.vect().y()/GeV<<","<<p.vect().z()/GeV<<") Mass = "<<p.mass()/GeV<<" m = "<<p.m()/GeV<<"\n";
 	}
 }
 */
 void MatrixElementClusterFissioner::doinit() {
 	ClusterFissioner::doinit();
 	// TODO: Some User warnings/errors but not complete list
 	if (_matrixElement!=0 && _fissionApproach==0) generator()->logWarning( Exception(
 				"For non-trivial MatrixElement you need to enable FissionApproach=New or Hybrid\n",
 				Exception::warning));
 }
 
 void MatrixElementClusterFissioner::Init() {
 	// TODO test for what can be copied
 	// std::cout << "sizeof Cluster "  << sizeof(Cluster) << std::endl;
 	// std::cout << "sizeof Axis "  << sizeof(Axis) << std::endl;
 	// std::cout << "sizeof Axis & "  << sizeof(Axis&) << std::endl;
 	// std::cout << "sizeof Axis * "  << sizeof(Axis*) << std::endl;
 	// std::cout << "sizeof energy "  << sizeof(Energy) << std::endl;
 	// std::cout << "sizeof energy2 "  << sizeof(Energy2) << std::endl;
 	// std::cout << "sizeof bool "  << sizeof(bool) << std::endl;
 	// std::cout << "sizeof energy &  "  << sizeof(Energy&) << std::endl;
 	// std::cout << "sizeof energy *  "  << sizeof(Energy*) << std::endl;
 
   static ClassDocumentation<MatrixElementClusterFissioner> documentation
     ("Class responsibles for chopping up the clusters");
 
   static Switch<MatrixElementClusterFissioner,int> interfaceFissionApproach
     ("FissionApproach",
      "Option for different Cluster Fission approaches",
      &MatrixElementClusterFissioner::_fissionApproach, 0, false, false);
   static SwitchOption interfaceFissionApproachDefault
     (interfaceFissionApproach,
      "Default",
      "Default Herwig-7.3.0 cluster fission without restructuring",
      0);
   static SwitchOption interfaceFissionApproachNew
     (interfaceFissionApproach,
      "New",
      "New cluster fission which allows to choose MassSampler"
 		 ", PhaseSpaceSampler and MatrixElement",
      1);
   static SwitchOption interfaceFissionApproachHybrid
     (interfaceFissionApproach,
      "Hybrid",
      "New cluster fission which allows to choose MassSampler"
 		 ", PhaseSpaceSampler and MatrixElement, but uses Default"
 		 " Approach for BeamClusters",
      2);
   static SwitchOption interfaceFissionApproachPreservePert
 		(interfaceFissionApproach,
      "PreservePert",
      "New cluster fission which allows to choose MassSampler"
 		 ", PhaseSpaceSampler and MatrixElement, but uses Default"
 		 " Approach for BeamClusters",
      3);
   static SwitchOption interfaceFissionApproachPreserveNonPert
 		(interfaceFissionApproach,
      "PreserveNonPert",
      "New cluster fission which allows to choose MassSampler"
 		 ", PhaseSpaceSampler and MatrixElement, but uses Default"
 		 " Approach for BeamClusters",
      4);
   static SwitchOption interfaceFissionApproachPreserveFirstPert
 		(interfaceFissionApproach,
      "PreserveFirstPert",
      "New cluster fission which allows to choose MassSampler"
 		 ", PhaseSpaceSampler and MatrixElement, but uses Default"
 		 " Approach for BeamClusters",
      5);
 
   // Switch C->H1,C2 C->H1,H2 on or off
   static Switch<MatrixElementClusterFissioner,int> interfaceAllowHadronFinalStates
     ("AllowHadronFinalStates",
      "Option for allowing hadron final states of cluster fission",
      &MatrixElementClusterFissioner::_allowHadronFinalStates, 0, false, false);
   static SwitchOption interfaceAllowHadronFinalStatesNone
     (interfaceAllowHadronFinalStates,
      "None",
      "Option for disabling hadron final states of cluster fission",
      0);
   static SwitchOption interfaceAllowHadronFinalStatesSemiHadronicOnly
     (interfaceAllowHadronFinalStates,
      "SemiHadronicOnly",
      "Option for allowing hadron final states of cluster fission of type C->H1,C2 "
 		 "(NOT YET USABLE WITH MatrixElement only use option None)",
      1);
   static SwitchOption interfaceAllowHadronFinalStatesAll
     (interfaceAllowHadronFinalStates,
      "All",
      "Option for allowing hadron final states of cluster fission "
 		 "of type C->H1,C2 or C->H1,H2 "
 		 "(NOT YET USABLE WITH MatrixElement only use option None)",
      2);
 
   // Mass Sampler Switch
   static Switch<MatrixElementClusterFissioner,int> interfaceMassSampler
     ("MassSampler",
      "Option for different Mass sampling options",
      &MatrixElementClusterFissioner::_massSampler, 0, false, false);
   static SwitchOption interfaceMassSamplerDefault
     (interfaceMassSampler,
      "Default",
      "Choose H7.2.3 default mass sampling using PSplitX",
      0);
   static SwitchOption interfaceMassSamplerUniform
     (interfaceMassSampler,
      "Uniform",
      "Choose Uniform Mass sampling in M1,M2 space",
      1);
   static SwitchOption interfaceMassSamplerFlatPhaseSpace
     (interfaceMassSampler,
      "FlatPhaseSpace",
      "Choose Flat Phase Space sampling of Mass in M1,M2 space (Recommended)",
      2);
   static SwitchOption interfaceMassSamplerPhaseSpacePowerLaw
     (interfaceMassSampler,
      "PhaseSpacePowerLaw",
      "Choose Phase Space times a power law sampling of Mass in M1,M2 space.",
      3);
 
   static Parameter<MatrixElementClusterFissioner,double>
     interfaceMassPowerLaw("MassPowerLaw",
 				"power of mass power law modulation of FlatPhaseSpace",
                     &MatrixElementClusterFissioner::_powerLawPower, 0.0, -10.0, 0.0, 10.0,
 		    false,false,false);
 
   // Phase Space Sampler Switch
   static Switch<MatrixElementClusterFissioner,int> interfacePhaseSpaceSamplerCluster
     ("PhaseSpaceSamplerCluster",
      "Option for different phase space sampling options",
      &MatrixElementClusterFissioner::_phaseSpaceSamplerCluster, 0, false, false);
   static SwitchOption interfacePhaseSpaceSamplerClusterAligned
     (interfacePhaseSpaceSamplerCluster,
      "Aligned",
      "Draw the momentum of child clusters to be aligned"
 		 " the relative momentum of the mother cluster",
      0);
   static SwitchOption interfacePhaseSpaceSamplerClusterIsotropic
     (interfacePhaseSpaceSamplerCluster,
      "Isotropic",
      "Draw the momentum of child clusters to be isotropic"
 		 " the relative momentum of the mother cluster",
      1);
   static SwitchOption interfacePhaseSpaceSamplerClusterTchannel
     (interfacePhaseSpaceSamplerCluster,
      "Tchannel",
      "Draw the momentum of child clusters to be t-channel like"
 		 " the relative momentum of the mother cluster"
 		 " i.e. cosTheta ~ 1/(1+A-cosTheta)^2",
      2);
 
   static Switch<MatrixElementClusterFissioner,int> interfacePhaseSpaceSamplerConstituents
     ("PhaseSpaceSamplerConstituents",
      "Option for different phase space sampling options",
      &MatrixElementClusterFissioner::_phaseSpaceSamplerConstituent, 0, false, false);
   static SwitchOption interfacePhaseSpaceSamplerConstituentsAligned
     (interfacePhaseSpaceSamplerConstituents,
      "Aligned",
      "Draw the momentum of the constituents of the child clusters "
 		 "to be aligned relative to the direction of the child cluster",
      0);
   static SwitchOption interfacePhaseSpaceSamplerConstituentsIsotropic
     (interfacePhaseSpaceSamplerConstituents,
      "Isotropic",
      "Draw the momentum of the constituents of the child clusters "
 		 "to be isotropic relative to the direction of the child cluster",
      1);
   static SwitchOption interfacePhaseSpaceSamplerConstituentsTchannel
     (interfacePhaseSpaceSamplerConstituents,
      "Exponential",
      "Draw the momentum of the constituents of the child clusters "
 		 "to be exponential relative to the direction of the child cluster"
 		 " i.e. cosTheta ~ exp(lam*(cosTheta-1)",
      2);
 
 
 
   // Matrix Element Choice Switch
   static Switch<MatrixElementClusterFissioner,int> interfaceMatrixElement
     ("MatrixElement",
      "Option for different Matrix Element options",
      &MatrixElementClusterFissioner::_matrixElement, 0, false, false);
   static SwitchOption interfaceMatrixElementDefault
     (interfaceMatrixElement,
      "Default",
      "Choose trivial matrix element i.e. whatever comes from the mass and "
 		 "phase space sampling",
      0);
   static SwitchOption interfaceMatrixElementSoftQQbarFinalFinal
     (interfaceMatrixElement,
      "SoftQQbarFinalFinal",
 		 "Choose Soft p1,p2->q1,q2,g*->q1,q2,q,qbar matrix element"
 		 "NOTE: Here the matrix element depends on qi.q(bar)",
      1);
   static SwitchOption interfaceMatrixElementSoftQQbarInitialFinal
     (interfaceMatrixElement,
      "SoftQQbarInitialFinal",
 		 "Choose Soft p1,p2->q1,q2,g*->q1,q2,q,qbar matrix element "
 		 "NOTE: Here the matrix element depends on pi.q(bar)",
      2);
   static SwitchOption interfaceMatrixElementTest
     (interfaceMatrixElement,
      "Test",
 		 "Choose Soft p1,p2->q1,q2,g*->q1,q2,q,qbar matrix element "
 		 "NOTE: Here the matrix element depends on pi.q(bar)",
      4);
   static SwitchOption interfaceMatrixElementSoftQQbarInitialFinalTchannel
     (interfaceMatrixElement,
      "SoftQQbarInitialFinalTchannel",
 		 "Choose Soft p1,p2->q1,q2,g*->q1,q2,q,qbar matrix element "
 		 "NOTE: Here the matrix element depends on pi.q(bar)",
      5);
 	// Technical Max loop parameter for New ClusterFission approach and Matrix Element 
 	// Rejection sampling
   static Parameter<MatrixElementClusterFissioner,int> interfaceMaxLoopMatrixElement
     ("MaxLoopMatrixElement",
      "Technical Parameter for how many tries are allowed to sample the "
 		 "Cluster Fission matrix element before reverting to fissioning "
 		 "using the default Fission Aproach",
      &MatrixElementClusterFissioner::_maxLoopFissionMatrixElement, 5000000, 100, 1e8,
 		 false, false, Interface::limited);
   static Switch<MatrixElementClusterFissioner,int> interfaceFailModeMaxLoopMatrixElement
     ("FailModeMaxLoopMatrixElement",
      "How to fail if we try more often than MaxLoopMatrixElement",
      &MatrixElementClusterFissioner::_failModeMaxLoopMatrixElement, 0, false, false);
   static SwitchOption interfaceDiquarkClusterFissionOldFission
 	(interfaceFailModeMaxLoopMatrixElement,
      "OldFission",
      "Use old Cluster Fission Aproach if we try more often than MaxLoopMatrixElement",
      0);
   static SwitchOption interfaceDiquarkClusterFissionRejectEvent
 	(interfaceFailModeMaxLoopMatrixElement,
      "RejectEvent",
      "Reject Event if we try more often than MaxLoopMatrixElement",
      1);
 
   static Switch<MatrixElementClusterFissioner,int> interfaceDiquarkClusterFission
     ("DiquarkClusterFission",
      "Allow clusters to fission to 1 or 2 diquark Clusters or Turn off diquark fission completely",
      &MatrixElementClusterFissioner::_diquarkClusterFission, 0, false, false);
   static SwitchOption interfaceDiquarkClusterFissionAll
 	(interfaceDiquarkClusterFission,
      "All",
      "Allow diquark clusters and baryon clusters to fission to new diquark Clusters",
      2);
   static SwitchOption interfaceDiquarkClusterFissionOnlyBaryonClusters
 	(interfaceDiquarkClusterFission,
      "OnlyBaryonClusters",
      "Allow only baryon clusters to fission to new diquark Clusters",
      1);
   static SwitchOption interfaceDiquarkClusterFissionNo
     (interfaceDiquarkClusterFission,
      "No",
      "Don't allow clusters to fission to new diquark Clusters",
      0);
   static SwitchOption interfaceDiquarkClusterFissionOff
     (interfaceDiquarkClusterFission,
      "Off",
      "Don't allow clusters fission to draw diquarks ",
      -1);
 
   // Matrix Element Choice Switch
   static Parameter<MatrixElementClusterFissioner,double>
     interfaceSafetyFactorOverEst("SafetyFactorOverEst","Safety factor with which the numerical overestimate is calculated",
 		  &MatrixElementClusterFissioner::_safetyFactorMatrixElement, 0, 10.0, 1.0, 1000.0,false,false,false);
   // Matrix Element IR cutoff
   static Parameter<MatrixElementClusterFissioner,double>
 		interfaceMatrixElementIRCutOff("MatrixElementResolutionCutOff",
 				"Resolution CutOff for MatrixElement t-channel with the Coloumb divergence. "
 				"for MatrixElement SoftQQbarInitialFinalTchannel e.g. such that 1/(t^2)->1/((t-_epsilonResolution*mGluonConst^2)^2)",
 		  &MatrixElementClusterFissioner::_epsilonResolution, 0, 0.01, 1e-6, 1000.0,false,false,false);
 	
   // Matrix Element Choice Switch
   static Switch<MatrixElementClusterFissioner,int> interfaceWriteOut
     ("WriteOut",
      "Option for different Matrix Element options",
      &MatrixElementClusterFissioner::_writeOut, 0, false, false);
   static SwitchOption interfaceWriteOutNo
     (interfaceWriteOut,
      "No",
      "Choose trivial matrix element i.e. whatever comes from the mass and "
 	 "phase space sampling",
      0);
   static SwitchOption interfaceWriteOutYes
     (interfaceWriteOut,
      "Yes",
 	 "Choose Soft q1,q2->q1,q2,g*->q1,q2,q,qbar matrix element",
      1);
 }
 tPVector MatrixElementClusterFissioner::fission(ClusterVector & clusters, bool softUEisOn) {
   // return if no clusters
   if (clusters.empty()) return tPVector();
 
   /*****************
    * Loop over the (input) collection of cluster pointers, and store in
    * the vector  splitClusters  all the clusters that need to be split
    * (these are beam clusters, if soft underlying event is off, and
    *  heavy non-beam clusters).
    ********************/
 
   stack<ClusterPtr> splitClusters;
   for(ClusterVector::iterator it = clusters.begin() ;
       it != clusters.end() ; ++it) {
     /**************
      * Skip 3-component clusters that have been redefined (as 2-component
      * clusters) or not available clusters. The latter check is indeed
      * redundant now, but it is used for possible future extensions in which,
      * for some reasons, some of the clusters found by ClusterFinder are tagged
      * straight away as not available.
      **************/
     if((*it)->isRedefined() || !(*it)->isAvailable()) continue;
     // if the cluster is a beam cluster add it to the vector of clusters
     // to be split or if it is heavy
     if((*it)->isBeamCluster() || isHeavy(*it)) splitClusters.push(*it);
   }
   tPVector finalhadrons;
   cut(splitClusters, clusters, finalhadrons, softUEisOn);
   return finalhadrons;
 }
 
 void MatrixElementClusterFissioner::cut(stack<ClusterPtr> & clusterStack,
    			   ClusterVector &clusters, tPVector & finalhadrons,
 			   bool softUEisOn) {
   /**************************************************
    * This method does the splitting of the cluster pointed by  cluPtr
    * and "recursively" by all of its cluster children, if heavy. All of these
    * new children clusters are added (indeed the pointers to them) to the
    * collection of cluster pointers  collecCluPtr. The method works as follows.
    * Initially the vector vecCluPtr contains just the input pointer to the
    * cluster to be split. Then it will be filled "recursively" by all
    * of the cluster's children that are heavy enough to require, in their turn,
    * to be split. In each loop, the last element of the vector vecCluPtr is
    * considered (only once because it is then removed from the vector).
    * This approach is conceptually recursive, but avoid the overhead of
    * a concrete recursive function. Furthermore it requires minimal changes
    * in the case that the fission of an heavy cluster could produce more
    * than two cluster children as assumed now.
    *
    * Draw the masses: for normal, non-beam clusters a power-like mass dist
    * is used, whereas for beam clusters a fast-decreasing exponential mass
    * dist is used instead (to avoid many iterative splitting which could
    * produce an unphysical large transverse energy from a supposed soft beam
    * remnant process).
    ****************************************/
   // Here we recursively loop over clusters in the stack and cut them
   while (!clusterStack.empty()) {
     // take the last element of the vector
     ClusterPtr iCluster = clusterStack.top(); clusterStack.pop();
     // split it
     cutType ct = iCluster->numComponents() == 2 ?
       cutTwo(iCluster, finalhadrons, softUEisOn) :
       cutThree(iCluster, finalhadrons, softUEisOn);
 
     // There are cases when we don't want to split, even if it fails mass test
     if(!ct.first.first || !ct.second.first) {
       // if an unsplit beam cluster leave if for the underlying event
       if(iCluster->isBeamCluster() && softUEisOn)
 	iCluster->isAvailable(false);
       continue;
     }
     // check if clusters
     ClusterPtr one = dynamic_ptr_cast<ClusterPtr>(ct.first.first);
     ClusterPtr two = dynamic_ptr_cast<ClusterPtr>(ct.second.first);
     // is a beam cluster must be split into two clusters
     if(iCluster->isBeamCluster() && (!one||!two) && softUEisOn) {
       iCluster->isAvailable(false);
       continue;
     }
 
     // There should always be a intermediate quark(s) from the splitting
     assert(ct.first.second && ct.second.second);
     /// \todo sort out motherless quark pairs here. Watch out for 'quark in final state' errors
     iCluster->addChild(ct.first.first);
     //    iCluster->addChild(ct.first.second);
     //    ct.first.second->addChild(ct.first.first);
 
     iCluster->addChild(ct.second.first);
     //    iCluster->addChild(ct.second.second);
     //    ct.second.second->addChild(ct.second.first);
 
     // Sometimes the clusters decay C -> H + C' or C -> H + H' rather then C -> C' + C''
     if(one) {
       clusters.push_back(one);
       if(one->isBeamCluster() && softUEisOn)
 	one->isAvailable(false);
       if(isHeavy(one) && one->isAvailable())
 	clusterStack.push(one);
     }
     if(two) {
       clusters.push_back(two);
       if(two->isBeamCluster() && softUEisOn)
 	two->isAvailable(false);
       if(isHeavy(two) && two->isAvailable())
 	clusterStack.push(two);
     }
   }
 }
 MatrixElementClusterFissioner::cutType
 MatrixElementClusterFissioner::cutTwo(ClusterPtr & cluster, tPVector & finalhadrons,
 			 bool softUEisOn) {
 	switch (_fissionApproach)
 	{
 		case 0:
 			return ClusterFissioner::cutTwo(cluster, finalhadrons, softUEisOn);
 			break;
 		case 1:
 			return cutTwoMatrixElement(cluster, finalhadrons, softUEisOn);
 			break;
 		case 2:
 			if (cluster->isBeamCluster()) {
 				return ClusterFissioner::cutTwo(cluster, finalhadrons, softUEisOn);
 			}
 			else {
 				return cutTwoMatrixElement(cluster, finalhadrons, softUEisOn);
 			}
 			break;
 		case 3:
 			{
 				bool isPert=false;
 				for (unsigned int i = 0; i < cluster->numComponents(); i++)
 				{
 					if (cluster->isPerturbative(i))
 						isPert=true;
 				}
 				if (isPert)
 					return ClusterFissioner::cutTwo(cluster, finalhadrons, softUEisOn);
 				else
 					return cutTwoMatrixElement(cluster, finalhadrons, softUEisOn);
 			break;
 			}
 		case 4:
 			{
 				bool isPert=false;
 				for (unsigned int i = 0; i < cluster->numComponents(); i++)
 				{
 					if (cluster->isPerturbative(i))
 						isPert=true;
 				}
 				if (!isPert)
 					return ClusterFissioner::cutTwo(cluster, finalhadrons, softUEisOn);
 				else
 					return cutTwoMatrixElement(cluster, finalhadrons, softUEisOn);
 			break;
 			}
 		case 5:
 			{
 				bool isPert=true;
 				for (unsigned int i = 0; i < cluster->numComponents(); i++)
 				{
 					if (!cluster->isPerturbative(i)) {
 						isPert=false;
 						break;
 					}
 				}
 				if (isPert)
 					return ClusterFissioner::cutTwo(cluster, finalhadrons, softUEisOn);
 				else
 					return cutTwoMatrixElement(cluster, finalhadrons, softUEisOn);
 			break;
 			}
 		default:
 			assert(false);
 	}
 }
 namespace {
 int areNotSame(const Lorentz5Momentum & p1,const Lorentz5Momentum & p2){
 	double tol=1e-5;
 	if (abs(p1.vect().x()-p2.vect().x())>tol*GeV){
 		std::cout << "disagreeing x " <<std::setprecision(-log10(tol)+2) << abs(p1.vect().x()-p2.vect().x())/GeV<< std::endl;
 		return 1;
 	}
 	if (abs(p1.vect().y()-p2.vect().y())>tol*GeV){
 		std::cout << "disagreeing y " <<std::setprecision(-log10(tol)+2)<< abs(p1.vect().y()-p2.vect().y())/GeV<< std::endl;
 		return 2;
 	}
 	if (abs(p1.vect().z()-p2.vect().z())>tol*GeV){
 		std::cout << "disagreeing z " <<std::setprecision(-log10(tol)+2)<< abs(p1.vect().z()-p2.vect().z())/GeV<< std::endl;
 		return 3;
 	}
 	if (abs(p1.e()-p2.e())>tol*GeV){
 		std::cout << "disagreeing e " <<std::setprecision(-log10(tol)+2)<< abs(p1.e()-p2.e())/GeV<< std::endl;
 		return 4;
 	}
 	if (abs(p1.m()-p2.m())>tol*GeV){
 		std::cout << "disagreeing m " <<std::setprecision(-log10(tol)+2)<< abs(p1.m()-p2.m())/GeV<< std::endl;
 		return 4;
 	}
 	if (abs(p1.m()-p1.mass())>tol*GeV){
 		std::cout << "disagreeing p1 m - mass " <<std::setprecision(-log10(tol)+2)<< abs(p1.m()-p1.mass())/GeV<< std::endl;
 		return 4;
 	}
 	if (abs(p2.m()-p2.mass())>tol*GeV){
 		std::cout << "disagreeing p2 m - mass " <<std::setprecision(-log10(tol)+2)<< abs(p2.m()-p2.mass())/GeV<< std::endl;
 		return 4;
 	}
 	return 0;
 }
 }
 MatrixElementClusterFissioner::cutType
 MatrixElementClusterFissioner::cutTwoMatrixElement(ClusterPtr & cluster, tPVector & finalhadrons,
 			 bool softUEisOn) {
   // need to make sure only 2-cpt clusters get here
   assert(cluster->numComponents() == 2);
   tPPtr ptrQ1 = cluster->particle(0);
   tPPtr ptrQ2 = cluster->particle(1);
 	Energy Mc = cluster->mass();
 	// TODO BEGIN Changed comp to default
 	if ( Mc < spectrum()->massLightestHadronPair(ptrQ1->dataPtr(),ptrQ2->dataPtr())) {
 		static const PPtr null = PPtr();
 		return cutType(PPair(null,null),PPair(null,null));
 	}
 	// TODO END Changed comp to default
   assert(ptrQ1);
   assert(ptrQ2);
 
   // And check if those particles are from a beam remnant
   bool rem1 = cluster->isBeamRemnant(0);
   bool rem2 = cluster->isBeamRemnant(1);
   // workout which distribution to use
   bool soft1(false),soft2(false);
   switch (_iopRem) {
   case 0:
     soft1 = rem1 || rem2;
     soft2 = rem2 || rem1;
     break;
   case 1:
     soft1 = rem1;
     soft2 = rem2;
     break;
   }
   // Initialization for the exponential ("soft") mass distribution.
   int counter_MEtry = 0;
   Energy Mc1 = ZERO;
 	Energy Mc2 = ZERO;
 	Energy m  = ZERO;
 	Energy m1 = ptrQ1->data().constituentMass();
 	Energy m2 = ptrQ2->data().constituentMass();
 	Energy mMin = getParticleData(ParticleID::d)->constituentMass();
 	// Minimal threshold for non-zero Mass PhaseSpace
 	if ( Mc < (m1 + m2 + 2*mMin )) {
 		static const PPtr null = PPtr();
 		return cutType(PPair(null,null),PPair(null,null));
 	}
   tcPDPtr toHadron1, toHadron2;
   PPtr newPtr1 = PPtr ();
   PPtr newPtr2 = PPtr ();
   Lorentz5Momentum pClu1, pClu2, pQ1, pQone, pQtwo, pQ2;
 	Lorentz5Momentum pClu = cluster->momentum(); // known
 	const Lorentz5Momentum p0Q1 = ptrQ1->momentum(); // known (mom Q1 before fission)
 	const Lorentz5Momentum p0Q2 = ptrQ2->momentum(); // known (mom Q2 before fission)
 	// where to return to in case of rejected sample
 	enum returnTo {
 		FlavourSampling,
 		MassSampling,
 		PhaseSpaceSampling,
 		MatrixElementSampling,
 		Done
 	};
 	// start with FlavourSampling
 	returnTo retTo=FlavourSampling;
 	int letFissionToXHadrons = _allowHadronFinalStates;
 	// if a beam cluster not allowed to decay to hadrons
 	if (cluster->isBeamCluster() && softUEisOn) letFissionToXHadrons = 0;
 	// ### Flavour, Mass, PhaseSpace and MatrixElement Sampling loop until accepted: ###
 	bool escape = false;
 	double weightMasses,weightPhaseSpaceAngles;
 	// TODO make this better
 	// TODO make this independent of explicit u/d quark
 	Energy mLightestQuark = getParticleData(ThePEG::ParticleID::u)->constituentMass();
 	if (mLightestQuark>getParticleData(ThePEG::ParticleID::d)->constituentMass())
 		mLightestQuark = getParticleData(ThePEG::ParticleID::d)->constituentMass();
 	double SQME,SQMEoverEstimate;
 	double weightFlatPS;
   do
   {
 	  switch (retTo)
 	  {
 			case FlavourSampling:
 			{
 				// ## Flavour sampling and kinematic constraints ##
 				drawNewFlavour(newPtr1,newPtr2,cluster);
 				// get a flavour for the qqbar pair
 				// check for right ordering
 				// careful if DiquarkClusters can exist
 				bool Q1diq = DiquarkMatcher::Check(ptrQ1->id());
 				bool Q2diq = DiquarkMatcher::Check(ptrQ2->id());
 				bool newQ1diq = DiquarkMatcher::Check(newPtr1->id());
 				bool newQ2diq = DiquarkMatcher::Check(newPtr2->id());
 				bool diqClu1 = Q1diq && newQ1diq;
 				bool diqClu2 = Q2diq && newQ2diq;
 				// DEBUG only:
 				// std::cout << "Make Clusters: ( " << ptrQ1->PDGName() << " " << newPtr1->PDGName() << " ), ( "
 				// << ptrQ2->PDGName() << " " << newPtr2->PDGName() << " )\n";
 				// check if Hadron formation is possible
 				if (!( diqClu1 || diqClu2 )
 						&& (cantMakeHadron(ptrQ1, newPtr1) || cantMakeHadron(ptrQ2, newPtr2))) {
 					swap(newPtr1, newPtr2);
 					// check again
 					if(cantMakeHadron(ptrQ1, newPtr1) || cantMakeHadron(ptrQ2, newPtr2)) {
 						throw Exception()
 							<< "MatrixElementClusterFissioner cannot split the cluster ("
 							<< ptrQ1->PDGName() << ' ' << ptrQ2->PDGName()
 							<< ") into hadrons.\n"
 							<< "drawn Flavour: "<< newPtr1->PDGName()<<"\n"<< Exception::runerror;
 					}
 				}
 				else if ( diqClu1 || diqClu2 ){
 					bool swapped=false;
 					if ( !diqClu1 && cantMakeHadron(ptrQ1,newPtr1) ) {
 						swap(newPtr1, newPtr2);
 						swapped=true;
 					}
 					if ( !diqClu2 && cantMakeHadron(ptrQ2,newPtr2) ) {
 						assert(!swapped);
 						swap(newPtr1, newPtr2);
 					}
 					if ( diqClu2 && diqClu1 && ptrQ1->id()*newPtr1->id()>0 ) {
 						assert(!swapped);
 						swap(newPtr1, newPtr2);
 					}
 					if (!diqClu1) assert(!cantMakeHadron(ptrQ1,newPtr1));
 					if (!diqClu2) assert(!cantMakeHadron(ptrQ2,newPtr2));
 				}
 				// Check that new clusters can produce particles and there is enough
 				// phase space to choose the drawn flavour
 				m  = newPtr1->data().constituentMass();
 				// Do not split in the case there is no phase space available + permille security
 				double eps=0.1;
 				if(Mc <  (1+eps)*(m1 + m + m2 + m))  {
 					retTo = FlavourSampling;
 					// escape if no flavour phase space possibile without fission
 					if (fabs((m - mMin)/GeV) < 1e-3) {
 						escape = true;
 						retTo = Done;
 					}
 					continue;
 				}
 				pQ1.setMass(m1);
 				pQone.setMass(m);
 				pQtwo.setMass(m);
 				pQ2.setMass(m2);
 				// Determined the (5-components) momenta (all in the LAB frame)
 				// p0Q1.setMass(ptrQ1->mass()); // known (mom Q1 before fission)
 				// p0Q1.rescaleEnergy(); // TODO check if needed
 				// p0Q2.setMass(ptrQ2->mass()); // known (mom Q2 before fission)
 				// p0Q2.rescaleEnergy();// TODO check if needed
 				pClu.rescaleMass();
 
 				Energy MLHP1 = spectrum()->hadronPairThreshold(ptrQ1->dataPtr(),newPtr1->dataPtr());
 				Energy MLHP2 = spectrum()->hadronPairThreshold(ptrQ2->dataPtr(),newPtr2->dataPtr());
 
 				Energy MLH1 = spectrum()->lightestHadron(ptrQ1->dataPtr(),newPtr1->dataPtr())->mass();
 				Energy MLH2 = spectrum()->lightestHadron(ptrQ2->dataPtr(),newPtr2->dataPtr())->mass();
 
 				bool canBeSingleHadron1 = (m1 + m) < MLHP1;
 				bool canBeSingleHadron2 = (m2 + m) < MLHP2;
 
 				Energy mThresh1 = (m1 + m);
 				Energy mThresh2 = (m2 + m);
 
 				if (canBeSingleHadron1) mThresh1 = MLHP1;
 				if (canBeSingleHadron2) mThresh2 = MLHP2;
 
 				switch (letFissionToXHadrons)
 				{
 					case 0:
 						{
 							// Option None: only C->C1,C2 allowed
 							// check if mass phase space is non-zero 
 							// resample or escape if only allowed mass phase space is for C->H1,H2 or C->H1,C2
 							if ( Mc < (mThresh1 + mThresh2)) {
 								// escape if not even the lightest flavour phase space is possibile
 								if ( fabs((m - mLightestQuark)/GeV) < 1e-3	) {
 									escape = true;
 									retTo = Done;
 									continue;
 								}
 								else {
 									retTo = FlavourSampling;
 									continue;
 								}
 							}
 							break;
 						}
 					case 1:
 						{
 							// Option SemiHadronicOnly: C->H,C allowed
 							// NOTE: TODO implement matrix element for this
 							// resample or escape if only allowed mass phase space is for C->H1,H2
 							// First case is for ensuring the enough mass to  be available and second one rejects disjoint mass regions
 							if ( ( (canBeSingleHadron1 && canBeSingleHadron2)
 									    &&  Mc < (mThresh1 + mThresh2) )
 									|| 
 									 ( (canBeSingleHadron1 || canBeSingleHadron2)
 								      && (canBeSingleHadron1 ? Mc-(m2+m) < MLH1:false ||  canBeSingleHadron2 ? Mc-(m1+m) < MLH2:false) )
 								 ){
 								// escape if not even the lightest flavour phase space is possibile
 								if (fabs((m - mLightestQuark)/GeV) < 1e-3 ) {
 									escape = true;
 									retTo = Done;
 									continue;
 								}
 								else {
 									retTo = FlavourSampling;
 									continue;
 								}
 							}
 							break;
 						}
 					case 2:
 						{
 							// Option All: C->H,C and C->H,H allowed
 							// NOTE: TODO implement matrix element for this
 							// Mass Phase space for all option can always be found if cluster massive enough to go
 							// to the lightest 2 hadrons
 							break;
 						}
 					default:
 						assert(false);
 				}
 				// Total overestimate of MatrixElement independent 
 				// of the PhaseSpace point and independent of M1,M2
 				SQMEoverEstimate = calculateSQME_OverEstimate(Mc,m1,m2,m); 
 				// Note: want to fallthrough (in C++17 one could uncomment
 				// 			 the line below to show that this is intentional)
 				[[fallthrough]];
 			}
 			/*
 			 * MassSampling choices:
 			 * 	- Default (default)
 			 * 	- Uniform
 			 * 	- FlatPhaseSpace
 			 * 	- SoftMEPheno
 			 * 	*/
 			case MassSampling:
 			{
 				weightMasses = drawNewMasses(Mc, soft1, soft2, pClu1, pClu2,
 						ptrQ1, pQ1, newPtr1, pQone,
 						newPtr2, pQtwo, ptrQ2, pQ2);
 
 				// TODO IF C->C1,C2 (and not C->C,H or H1,H2) masses sampled and is in PhaseSpace must push through
 				// because otherwise no matrix element
 				if(weightMasses==0.0) {
 					// TODO check which option is better
 					retTo = FlavourSampling;
 					// retTo = MassSampling;
 					continue;
 				}
 
 				// derive the masses of the children
 				Mc1 = pClu1.mass();
 				Mc2 = pClu2.mass();
 				// static kinematic threshold
 				if(_kinematicThresholdChoice != 1 )
 				{
 					// NOTE: that the squared thresholds below are 
 					// numerically more stringent which is needed
 					// kaellen function calculation
 					if(sqr(Mc1) < sqr(m1+m) || sqr(Mc2) < sqr(m+m2) || sqr(Mc1+Mc2) > sqr(Mc)){
 						// TODO check which option is better
 						// retTo = FlavourSampling;
 						retTo = MassSampling;
 						continue;
 					}
 					// dynamic kinematic threshold
 				} 
 				else if(_kinematicThresholdChoice == 1) {
 					bool C1 = ( sqr(Mc1) )/( sqr(m1) + sqr(m) + _kinThresholdShift ) < 1.0 ? true : false;
 					bool C2 = ( sqr(Mc2) )/( sqr(m2) + sqr(m) + _kinThresholdShift ) < 1.0 ? true : false;
 					bool C3 = ( sqr(Mc1) + sqr(Mc2) )/( sqr(Mc) ) > 1.0 ? true : false;
 
 					if( C1 || C2 || C3 ) {
 						// TODO check which option is better
 						// retTo = FlavourSampling;
 						retTo = MassSampling;
 						continue;
 					}
 				}
 				else 
 					assert(false);
 				/**************************
 				 * New (not present in Fortran Herwig):
 				 * check whether the fragment masses  Mc1  and  Mc2  are above the
 				 * threshold for the production of the lightest pair of hadrons with the
 				 * right flavours. If not, then set by hand the mass to the lightest
 				 * single hadron with the right flavours, in order to solve correctly
 				 * the kinematics, and (later in this method) create directly such hadron
 				 * and add it to the children hadrons of the cluster that undergoes the
 				 * fission (i.e. the one pointed by iCluPtr). Notice that in this special
 				 * case, the heavy cluster that undergoes the fission has one single
 				 * cluster child and one single hadron child. We prefer this approach,
 				 * rather than to create a light cluster, with the mass set equal to
 				 * the lightest hadron, and let then the class LightClusterDecayer to do
 				 * the job to decay it to that single hadron, for two reasons:
 				 * First, because the sum of the masses of the two constituents can be,
 				 * in this case, greater than the mass of that hadron, hence it would
 				 * be impossible to solve the kinematics for such two components, and
 				 * therefore we would have a cluster whose components are undefined.
 				 * Second, the algorithm is faster, because it avoids the reshuffling
 				 * procedure that would be necessary if we used LightClusterDecayer
 				 * to decay the light cluster to the lightest hadron.
 				 ****************************/
 				// override chosen masses if needed 
 				toHadron1 = spectrum()->chooseSingleHadron(ptrQ1->dataPtr(), newPtr1->dataPtr(),Mc1);
 				if ( letFissionToXHadrons == 0 && toHadron1 ) {
 					// reject mass samples which would force C->C,H or C->H1,H2 fission if desired 
 					//
 					// Check if Mc1max < MLHP1, in which case we might need to choose a different flavour
 					// else resampling the masses should be sufficient
 					Energy MLHP1 = spectrum()->massLightestHadronPair(ptrQ1->dataPtr(), newPtr1->dataPtr());
 					Energy MLHP2 = spectrum()->massLightestHadronPair(ptrQ2->dataPtr(), newPtr2->dataPtr());
 					Energy Mc1max = (m2+m) > MLHP2 ? (Mc-(m2+m)):(Mc-MLHP2);
 					// for avoiding inf loops set min threshold
 					if ( Mc1max - MLHP1 < 1e-2*GeV ) {
 						retTo = FlavourSampling;
 					}
 					else {
 						retTo = MassSampling;
 					}
 					continue;
 				}
 				if(toHadron1) {
 					Mc1 = toHadron1->mass();
 					pClu1.setMass(Mc1);
 				}
 				toHadron2 = spectrum()->chooseSingleHadron(ptrQ2->dataPtr(), newPtr2->dataPtr(),Mc2);
 				if ( letFissionToXHadrons == 0 && toHadron2 ) {
 					// reject mass samples which would force C->C,H or C->H1,H2 fission if desired 
 					//
 					// Check if Mc2max < MLHP2, in which case we might need to choose a different flavour
 					// else resampling the masses should be sufficient
 					Energy MLHP1 = spectrum()->massLightestHadronPair(ptrQ1->dataPtr(), newPtr1->dataPtr());
 					Energy MLHP2 = spectrum()->massLightestHadronPair(ptrQ2->dataPtr(), newPtr2->dataPtr());
 					Energy Mc2max = (m1+m) > MLHP1 ? (Mc-(m1+m)):(Mc-MLHP1);
 					// for avoiding inf loops set min threshold
 					if ( Mc2max - MLHP2 < 1e-2*GeV ) {
 						retTo = FlavourSampling;
 					}
 					else {
 						retTo = MassSampling;
 					}
 					continue;
 				}
 				if(toHadron2) {
 					Mc2 = toHadron2->mass();
 					pClu2.setMass(Mc2);
 				}
 				if (letFissionToXHadrons == 1 && (toHadron1 && toHadron2) ) {
 					// reject mass samples which would force C->H1,H2 fission if desired 
 					// TODO check which option is better
 					// retTo = FlavourSampling;
 					retTo = MassSampling;
 					continue;
 				}
 				// Check if the decay kinematics is still possible: if not then
 				// force the one-hadron decay for the other cluster as well.
 				// NOTE: that the squared thresholds below are 
 				// numerically more stringent which is needed
 				// kaellen function calculation
 				if(sqr(Mc1 + Mc2)  >  sqr(Mc)) {
 					// reject if we would need to create a C->H,H process if letFissionToXHadrons<2
 					if (letFissionToXHadrons < 2) {
 						// TODO check which option is better
 						// retTo = FlavourSampling;
 						retTo = MassSampling;
 						continue;
 					}
 
 					// TODO forbid other cluster!!!! to be also at hadron
 					if(!toHadron1) {
 						toHadron1 = spectrum()->chooseSingleHadron(ptrQ1->dataPtr(), newPtr1->dataPtr(),Mc-Mc2);
 						// toHadron1 = spectrum()->chooseSingleHadron(ptrQ1->dataPtr(), newPtr1->dataPtr(),ZERO);
 						if(toHadron1) {
 							Mc1 = toHadron1->mass();
 							pClu1.setMass(Mc1);
 						}
 					}
 					else if(!toHadron2) {
 						toHadron2 = spectrum()->chooseSingleHadron(ptrQ2->dataPtr(), newPtr2->dataPtr(),Mc-Mc1);
 						// toHadron2 = spectrum()->chooseSingleHadron(ptrQ2->dataPtr(), newPtr2->dataPtr(),ZERO);
 						if(toHadron2) {
 							Mc2 = toHadron2->mass();
 							pClu2.setMass(Mc2);
 						}
 					}
 				}
 				// NOTE: that the squared thresholds below are 
 				// numerically more stringent which is needed
 				// kaellen function calculation
 				if (sqr(Mc) <= sqr(Mc1+Mc2)){
 					// escape if already lightest quark drawn
 					if (fabs((m - mLightestQuark)/GeV) < 1e-3 ) {
 						// escape = true;
 						retTo = Done;
 					}
 					else {
 						// Try again with lighter quark
 						retTo = FlavourSampling;
 					}
 					continue;
 				}
 				// weight(M1,M2) for M1*M2*(Two body PhaseSpace)**3 should be in [0,1]
 				weightFlatPS = weightFlatPhaseSpace(Mc, Mc1, Mc2, m, m1, m2, ptrQ1, ptrQ2, newPtr1);
 				// Note: want to fallthrough (in C++17 one could uncomment
 				// 			 the line below to show that this is intentional)
 				[[fallthrough]];
 			}
 			/*
 			 * PhaseSpaceSampling choices:
 			 * 	- FullyAligned (default)
 			 * 	- AlignedIsotropic
 			 * 	- FullyIsotropic
 			 * 	*/
 			case PhaseSpaceSampling:
 			{
 				// ### Sample the Phase Space with respect to Matrix Element: ###
 				// TODO insert here PhaseSpace sampler
 				weightPhaseSpaceAngles = drawKinematics(pClu,p0Q1,p0Q2,toHadron1,toHadron2,
 						pClu1,pClu2,pQ1,pQone,pQtwo,pQ2);
 				if(weightPhaseSpaceAngles==0.0) {
 					// TODO check which option is better
 					retTo = MassSampling;
 					continue;
 				}
 				// Activate only if needed
 				if (0)
 				{ //sanity
 					if (areNotSame(pClu1+pClu2,pClu)) {
 						std::cout << "PCLU" << std::endl;
 					}
 					if (areNotSame(pClu1,pQ1+pQone)) {
 						std::cout << "PCLU1" << std::endl;
 					}
 					if (areNotSame(pClu2,pQ2+pQtwo)) {
 						std::cout << "PCLU2" << std::endl;
 					}
 					if (areNotSame(pClu,pQ1+pQone+pQ2+pQtwo)) {
 						std::cout << "PTOT" << std::endl;
 					}
 				}
 
 				// Should be precise i.e. no rejection expected
 				// Note: want to fallthrough (in C++17 one could uncomment
 				// 			 the line below to show that this is intentional)
 				[[fallthrough]];
 			}
 			/*
 			 * MatrixElementSampling choices:
 			 * 	- Default (default)
 			 * 	- SoftQQbar
 			 * 	*/
 			case MatrixElementSampling:
 			{
 				counter_MEtry++;
 				// TODO maybe bridge this to work more neatly
 				// Ignore matrix element for C->C,H or C->H1,H2 fission
 				if (toHadron1 || toHadron2) {
 					retTo = Done;
 					break;
 				}
 				// Actual MatrixElement evaluated at sampled PhaseSpace point
 				SQME = calculateSQME(p0Q1,p0Q2,pQ1,pQone,pQ2,pQtwo);
 				// weight for MatrixElement*PhaseSpace must be in [0:1]
 				double weightSQME = SQME/SQMEoverEstimate;
 				assert(weightSQME>0.0);
 				if (weightFlatPS<0 || weightFlatPS>1.0){
 					throw Exception() << "weightFlatPS = "<< weightFlatPS << " > 1 or negative in MatrixElementClusterFissioner::cutTwo"
 						<< "Mc  = " << Mc/GeV
 						<< "Mc1 = " << Mc1/GeV
 						<< "Mc2 = " << Mc2/GeV
 						<< "m1  = " << m1/GeV
 						<< "m2  = " << m2/GeV
 						<< "m   = " << m/GeV
 						<< "SQME   = " << SQME
 						<< "SQME_OE   = " << SQMEoverEstimate
 						<< "PS   = " << weightFlatPS
 						<< Exception::runerror;
 				}
 				// current phase space point is distributed according to weightSamp
 				double Pacc = weightFlatPS * weightSQME;
 				double SamplingWeight = weightMasses * weightPhaseSpaceAngles;
 				if (!(SamplingWeight >= 0 ) || std::isnan(SamplingWeight) || std::isinf(SamplingWeight)){
 					throw Exception() << "SamplingWeight = "<< SamplingWeight << " in MatrixElementClusterFissioner::cutTwo"
 						<< "Mc  = " << Mc/GeV
 						<< "Mc1 = " << Mc1/GeV
 						<< "Mc2 = " << Mc2/GeV
 						<< "m1  = " << m1/GeV
 						<< "m2  = " << m2/GeV
 						<< "m   = " << m/GeV
 						<< "weightMasses   = " << weightMasses
 						<< "weightPhaseSpaceAngles   = " << weightPhaseSpaceAngles
 						<< "PS   = " << weightFlatPS
 						<< Exception::runerror;
 				}
 				Pacc/=SamplingWeight;
 				if (!(Pacc >= 0 ) || std::isnan(Pacc) || std::isinf(Pacc)){
 					throw Exception() << "Pacc = "<< Pacc << " < 0 in MatrixElementClusterFissioner::cutTwo"
 						<< "Mc  = " << Mc/GeV
 						<< "Mc1 = " << Mc1/GeV
 						<< "Mc2 = " << Mc2/GeV
 						<< "m1  = " << m1/GeV
 						<< "m2  = " << m2/GeV
 						<< "m   = " << m/GeV
 						<< "SQME   = " << SQME
 						<< "SQME_OE   = " << SQMEoverEstimate
 						<< "PS   = " << weightFlatPS
 						<< Exception::runerror;
 				}
 				assert(Pacc >= 0.0);
 				if (_matrixElement!=0) {
 					if ( Pacc > 1.0){
 						countPaccGreater1();
 						throw Exception() << "Pacc = "<< Pacc << " > 1 in MatrixElementClusterFissioner::cutTwo"
 							<< "Mc  = " << Mc/GeV
 							<< "Mc1 = " << Mc1/GeV
 							<< "Mc2 = " << Mc2/GeV
 							<< "m1  = " << m1/GeV
 							<< "m2  = " << m2/GeV
 							<< "m   = " << m/GeV
 							<< Exception::warning;
 					}
 				}
 				static int first=_writeOut;
 				if (_matrixElement==0  || UseRandom::rnd()<Pacc) { //Always accept a sample if trivial matrix element
 					if (_writeOut) {
 						// std::cout << "\nAccept Pacc = "<<Pacc<<"\n";
 						std::ofstream out("data_CluFis.dat", std::ios::app | std::ios::out);
 						Lorentz5Momentum p0Q1tmp(p0Q1);
 						Lorentz5Momentum pClu1tmp(pClu1);
 						Lorentz5Momentum pClu2tmp(pClu2);
 						p0Q1tmp.boost(-pClu.boostVector());
 						pClu1tmp.boost(-pClu.boostVector());
 						double cosThetaP1C1=p0Q1tmp.vect().cosTheta(pClu1tmp.vect());
 						out << Pacc << "\t"
 							<< Mc/GeV  << "\t"
 							<< pClu1.mass()/GeV << "\t"
 							<< pClu2.mass()/GeV << "\t"
 							<< pQone*pQtwo/(pQone.mass()*pQtwo.mass()) << "\t"
 							<< pQ1*pQ2/(pQ1.mass()*pQ2.mass()) << "\t"
 							<< pQ1*pQtwo/(pQ1.mass()*pQtwo.mass()) << "\t"
 							<< pQ2*pQone/(pQ2.mass()*pQone.mass()) << "\t"
 							<< p0Q1*(pQone+pQtwo)/(p0Q1.mass()*(pQone.mass()+pQtwo.mass())) << "\t"
 							<< p0Q2*(pQone+pQtwo)/(p0Q2.mass()*(pQone.mass()+pQtwo.mass())) << "\t"
 							<< m/GeV << "\t"
 							<< cosThetaP1C1
 							<< "\n";
 						out.close();
 						Energy MbinStart=2.0*GeV;
 						Energy MbinEnd=91.0*GeV;
 						Energy dMbin=1.0*GeV;
 						Energy MbinLow;
 						Energy MbinHig;
 						if (   fabs((m-getParticleData(ParticleID::d)->constituentMass())/GeV)<1e-5
 							&& fabs((m1-getParticleData(ParticleID::d)->constituentMass())/GeV)<1e-5
 							&& fabs((m2-getParticleData(ParticleID::d)->constituentMass())/GeV)<1e-5) {
 							int cnt = 0;
 							for (Energy MbinIt=MbinStart; MbinIt < MbinEnd; MbinIt+=dMbin)
 							{
 								if (first){
 									first=0;
 									std::cout << "\nFirst\n" << std::endl;
 									int ctr=0;
 									for (Energy MbinIt=MbinStart; MbinIt < MbinEnd; MbinIt+=dMbin)
 									{
 										std::string name = "WriteOut/data_CluFis_BinM_"+std::to_string(ctr)+".dat";
 										std::ofstream out2(name,std::ios::out);
 										out2 << "# Binned from "<<MbinIt/GeV << "\tto\t" << (MbinIt+dMbin)/GeV<<"\n";
 										out2 << "# m=m1=m2=0.325\n";
 										out2 << "# (1) Pacc\t"
 											<< "(2) Mc/GeV\t"
 											<< "(3) M1/GeV\t"
 											<< "(4) M2/GeV\t"
 											<< "(5) q.qbar/(mq^2)\t"
 											<< "(6) q1.q2/(m1*m2)\t"
 											<< "(7) q1.qbar/(m1*mq)\t"
 											<< "(8) q2.q/(m2*mq)\t"
 											<< "(9) p1.(q+qbar)/(m1*2*mq)\t"
 											<< "(10) p2.(q+qbar)/(m2*2*mq)\t"
 											<< "(11) m/GeV\t"
 											<< "(12) cos(theta_p1_Q1)\n";
 										out2.close();
 										ctr++;
 									}
 									// first=0;
 								}
 								MbinLow  = MbinIt;
 								MbinHig  = MbinLow+dMbin;
 								if (Mc>MbinLow && Mc<MbinHig) {
 									std::string name = "WriteOut/data_CluFis_BinM_"+std::to_string(cnt)+".dat";
 									std::ofstream out2(name, std::ios::app );
 									Lorentz5Momentum p0Q1tmp(p0Q1);
 									Lorentz5Momentum pClu1tmp(pClu1);
 									Lorentz5Momentum pClu2tmp(pClu2);
 									p0Q1tmp.boost(-pClu.boostVector());
 									pClu1tmp.boost(-pClu.boostVector());
 									double cosThetaP1C1=p0Q1tmp.vect().cosTheta(pClu1tmp.vect());
 									out2 << Pacc << "\t"
 										<< Mc/GeV  << "\t"
 										<< pClu1.mass()/GeV << "\t"
 										<< pClu2.mass()/GeV << "\t"
 										<< pQone*pQtwo/(pQone.mass()*pQtwo.mass()) << "\t"
 										<< pQ1*pQ2/(pQ1.mass()*pQ2.mass()) << "\t"
 										<< pQ1*pQtwo/(pQ1.mass()*pQtwo.mass()) << "\t"
 										<< pQ2*pQone/(pQ2.mass()*pQone.mass()) << "\t"
 										<< p0Q1*(pQone+pQtwo)/(p0Q1.mass()*(pQone.mass()+pQtwo.mass())) << "\t"
 										<< p0Q2*(pQone+pQtwo)/(p0Q2.mass()*(pQone.mass()+pQtwo.mass())) << "\t"
 										<< m/GeV << "\t"
 										<< cosThetaP1C1
 										<< "\n";
 									out2.close();
 									break;
 								}
 								// if (Mc<MbinIt) break;
 								cnt++;
 							}
 						}
 					}
 					retTo=Done;
 					break;
 				}
 				retTo = MassSampling;
 				continue;
 			}
 			default:
 			{
 				assert(false);
 			}
 	  }
   }
   while (retTo!=Done && !escape && counter_MEtry < _maxLoopFissionMatrixElement);
 
   if(escape) {
 		// happens if we get at too light cluster to begin with
 		static const PPtr null = PPtr();
 		return cutType(PPair(null,null),PPair(null,null));
   }
 
   if(counter_MEtry >= _maxLoopFissionMatrixElement) {
 		countMaxLoopViolations();
 		// happens if we get too massive clusters where the matrix element
 		// is very inefficiently sampled
 		std::stringstream warning;
 		warning
 			<< "Matrix Element rejection sampling tried more than "
 			<< counter_MEtry
 			<< " times.\nMcluster = " << Mc/GeV
 			<< "GeV\nm1 = " << m1/GeV
 			<< "GeV\nm2 = " << m2/GeV
 			<< "GeV\nm  = " << m/GeV
 			<< "GeV\n"
 			<< "isBeamCluster = " << cluster->isBeamCluster()
 			<<"Using default as MatrixElementClusterFissioner::cutTwo as a fallback.\n"
 			<< "***This Exception should not happen too often!*** ";
 		generator()->logWarning( Exception(warning.str(),Exception::warning));
 		switch (_failModeMaxLoopMatrixElement)
 		{
 			case 0:
 				// OldFission
 				return ClusterFissioner::cutTwo(cluster,finalhadrons,softUEisOn);
 				break;
 			case 1:
 				// RejectEvent
 				throw Exception() << warning.str()
 					<< Exception::eventerror;
 				break;
 			default:
 				assert(false);
 		}
   }
 	assert(abs(Mc1-pClu1.m())<1e-2*GeV);
 	assert(abs(Mc2-pClu2.m())<1e-2*GeV);
 	assert(abs(Mc1-pClu1.mass())<1e-2*GeV);
 	assert(abs(Mc2-pClu2.mass())<1e-2*GeV);
 	{
 		Lorentz5Momentum pp1(p0Q1);
 		Lorentz5Momentum pclu1(pClu1);
 		pclu1.boost(-pClu.boostVector());
 		pp1.boost(-pClu.boostVector());
 		// std::ofstream out("testCF.dat", std::ios::app);
 		// out << pclu1.vect().cosTheta(pp1.vect())<<"\n";
 		// out.close();
  }
 	// Count successfull ClusterFission
 	countFissionMatrixElement();
   // ==> full sample generated
   /******************
    * The previous methods have determined the kinematics and positions
    * of C -> C1 + C2.
    * In the case that one of the two product is light, that means either
    * decayOneHadronClu1 or decayOneHadronClu2 is true, then the momenta
    * of the components of that light product have not been determined,
    * and a (light) cluster will not be created: the heavy father cluster
    * decays, in this case, into a single (not-light) cluster and a
    * single hadron. In the other, "normal", cases the father cluster
    * decays into two clusters, each of which has well defined components.
    * Notice that, in the case of components which point to particles, the
    * momenta of the components is properly set to the new values, whereas
    * we do not change the momenta of the pointed particles, because we
    * want to keep all of the information (that is the new momentum of a
    * component after the splitting, which is contained in the _momentum
    * member of the Component class, and the (old) momentum of that component
    * before the splitting, which is contained in the momentum of the
    * pointed particle). Please not make confusion of this only apparent
    * inconsistency!
    ********************/
   LorentzPoint posC,pos1,pos2;
   posC = cluster->vertex();
   calculatePositions(pClu, posC, pClu1, pClu2, pos1, pos2);
   cutType rval;
   if(toHadron1) {
     rval.first = produceHadron(toHadron1, newPtr1, pClu1, pos1);
     finalhadrons.push_back(rval.first.first);
   }
   else {
     rval.first = produceCluster(ptrQ1, newPtr1, pClu1, pos1, pQ1, pQone, rem1);
   }
   if(toHadron2) {
     rval.second = produceHadron(toHadron2, newPtr2, pClu2, pos2);
     finalhadrons.push_back(rval.second.first);
   }
   else {
     rval.second = produceCluster(ptrQ2, newPtr2, pClu2, pos2, pQ2, pQtwo, rem2);
   }
   return rval;
 }
 
 /**
  * Calculate the masses and possibly kinematics of the cluster
  * fission at hand; if claculateKineamtics is perfomring non-trivial
  * steps kinematics calulcated here will be overriden. Currently resorts to the default
  * @return the potentially non-trivial distribution weight=f(M1,M2)
  *         On Failure we return 0
  */ 
 double MatrixElementClusterFissioner::drawNewMasses(const Energy Mc, const bool soft1, const bool soft2,
 		Lorentz5Momentum& pClu1, Lorentz5Momentum& pClu2,
 		tcPPtr ptrQ1,    const Lorentz5Momentum& pQ1, 
 		tcPPtr newPtr1, const Lorentz5Momentum& pQone,
 		tcPPtr, const Lorentz5Momentum& pQtwo,
 		tcPPtr ptrQ2,    const Lorentz5Momentum& pQ2) const {
 	// TODO	add precise weightMS that could be used used for improving the rejection Sampling
 	switch (_massSampler)
 	{
 		case 0:
 			return ClusterFissioner::drawNewMasses(Mc, soft1, soft2, pClu1, pClu2, ptrQ1, pQ1, tcPPtr(), pQone, tcPPtr(),pQtwo, ptrQ2, pQ2);
 			break;
 		case 1: 
 			return drawNewMassesUniform(Mc, pClu1, pClu2, pQ1, pQone, pQ2);
 			break;
 		case 2:
 			return drawNewMassesPhaseSpace(Mc, pClu1, pClu2, pQ1, pQone, pQ2, ptrQ1, newPtr1, ptrQ2);
 			break;
 		case 3:
 			return drawNewMassesPhaseSpacePowerLaw(Mc, pClu1, pClu2, pQ1, pQone, pQ2, ptrQ1, newPtr1, ptrQ2);
 			break;
 		default:
 			assert(false);
 	}
 	return 0;// failure
 }
 
 
 /**
  * Sample the masses for flat phase space
  * */
 double MatrixElementClusterFissioner::drawNewMassesUniform(const Energy Mc, Lorentz5Momentum& pClu1, Lorentz5Momentum& pClu2,
 		const Lorentz5Momentum& pQ1, 
 		const Lorentz5Momentum& pQ,
 		const Lorentz5Momentum& pQ2) const {
 
 	Energy M1,M2;
 	const Energy m1 = pQ1.mass();
 	const Energy m2 = pQ2.mass();
 	const Energy m  = pQ.mass();
 	const Energy M1min = m1 + m;
 	const Energy M2min = m2 + m;
 	const Energy M1max = Mc - M2min;
 	const Energy M2max = Mc - M1min;
 
 	assert(M1max-M1min>ZERO);
 	assert(M2max-M2min>ZERO);
 
 	double r1;
 	double r2;
 
 	int counter = 0;
 	const int max_counter = 100;
 
 	while (counter < max_counter) {
 		r1 = UseRandom::rnd();
 		r2 = UseRandom::rnd();
 
 		M1 = (M1max-M1min)*r1 + M1min;
 		M2 = (M2max-M2min)*r2 + M2min;
 
 		counter++;
 		if ( Mc > M1 + M2) break;
 	}
 
 	if (counter==max_counter
 			|| Mc < M1 + M2
 			|| M1 <= M1min
 			|| M2 <= M2min ) return 0.0; // failure
 
 	pClu1.setMass(M1);
 	pClu2.setMass(M2);
 
 	return 1.0; // succeeds
 }
 /**
  * Sample the masses for flat phase space
  * */
 double MatrixElementClusterFissioner::drawNewMassesPhaseSpacePowerLaw(const Energy Mc,
 		Lorentz5Momentum& pClu1, Lorentz5Momentum& pClu2,
 		const Lorentz5Momentum& pQ1, 
 		const Lorentz5Momentum& pQ,
 		const Lorentz5Momentum& pQ2,
 		tcPPtr ptrQ1, tcPPtr ptrQ2, tcPPtr ptrQ) const {
 	Energy M1,M2,MuS;
 	const Energy m1 = pQ1.mass();
 	const Energy m2 = pQ2.mass();
 	const Energy m  = pQ.mass();
 	const Energy M1min = m1 + m;
 	const Energy M2min = m2 + m;
 	const Energy M1max = Mc - M2min;
 	const Energy M2max = Mc - M1min;
 
 	assert(M1max-M1min>ZERO);
 	assert(M2max-M2min>ZERO);
 
 	double r1;
 	double r2;
 
 	int counter = 0;
 	const int max_counter = 200;
 
 	while (counter < max_counter) {
 		r1 = UseRandom::rnd();
 		r2 = UseRandom::rnd();
 
 		M1 = (M1max-M1min)*r1 + M1min;
 		M2 = (M2max-M2min)*r2 + M2min;
 
 		counter++;
 		if (sqr(M1+M2)>sqr(Mc))
 			continue;
 
 		// if (!phaseSpaceVeto(Mc,M1,M2,m,m1,m2) ) break; // For FlatPhaseSpace sampling vetoing
 		if (!phaseSpaceVeto(Mc,M1,M2,m,m1,m2, ptrQ1, ptrQ2, ptrQ,_powerLawPower) ) break; // For FlatPhaseSpace sampling vetoing
 	}
 	if (counter==max_counter) return 0.0; // failure
 
 	pClu1.setMass(M1);
 	pClu2.setMass(M2);
 
 	return weightPhaseSpaceConstituentMasses(Mc, M1, M2, m, m1, m2, _powerLawPower); // succeeds return weight
 }
 
 
 /**
  * Sample the masses for flat phase space
  * */
 double MatrixElementClusterFissioner::drawNewMassesPhaseSpace(const Energy Mc,
 		Lorentz5Momentum& pClu1, Lorentz5Momentum& pClu2,
 		const Lorentz5Momentum& pQ1, 
 		const Lorentz5Momentum& pQ,
 		const Lorentz5Momentum& pQ2,
 		tcPPtr ptrQ1, tcPPtr ptrQ2, tcPPtr ptrQ ) const {
 	Energy M1,M2,MuS;
 	const Energy m1 = pQ1.mass();
 	const Energy m2 = pQ2.mass();
 	const Energy m  = pQ.mass();
 	const Energy M1min = m1 + m;
 	const Energy M2min = m2 + m;
 	const Energy M1max = Mc - M2min;
 	const Energy M2max = Mc - M1min;
 
 	assert(M1max-M1min>ZERO);
 	assert(M2max-M2min>ZERO);
 
 	double r1;
 	double r2;
 
 	int counter = 0;
 	const int max_counter = 200;
 
 	while (counter < max_counter) {
 		r1 = UseRandom::rnd();
 		r2 = UseRandom::rnd();
 
 		M1 = (M1max-M1min)*r1 + M1min;
 		M2 = (M2max-M2min)*r2 + M2min;
 
 		counter++;
 		if (sqr(M1+M2)>sqr(Mc))
 			continue;
 
 		// if (!phaseSpaceVeto(Mc,M1,M2,m,m1,m2) ) break; // For FlatPhaseSpace sampling vetoing
 		if (!phaseSpaceVeto(Mc,M1,M2,m,m1,m2, ptrQ1, ptrQ2, ptrQ) ) break; // For FlatPhaseSpace sampling vetoing
 	}
 	if (counter==max_counter) return 0.0; // failure
 
 	pClu1.setMass(M1);
 	pClu2.setMass(M2);
 
 	return weightFlatPhaseSpace(Mc, M1, M2, m, m1, m2, ptrQ1, ptrQ2, ptrQ); // succeeds return weight
 }
 std::pair<Axis,double> MatrixElementClusterFissioner::sampleDirectionConstituents(
 		const Lorentz5Momentum & pClu, const Energy Mcluster)  const {
 		switch (_phaseSpaceSamplerConstituent)
 		{
 			case 0:
 				{
 					// Aligned
 					return std::make_pair(pClu.vect().unit(),1.0);
 				}
 			case 1:
 				{
 					// Isotropic
 					return std::make_pair(sampleDirectionIsotropic(),1.0);
 				}
 			case 2:
 			{
 				// Exponential
 				// New
 				// double C_est_Exponential=1.18;
 				// double power_est_Exponential=0.65;
 				// Old 
 				double C_est_Exponential=0.63;
 				double power_est_Exponential=0.89;
 				double lambda=C_est_Exponential*pow(Mcluster/GeV,power_est_Exponential);
 				return sampleDirectionExponential(pClu.vect().unit(), lambda);
 			}
 			default:
 				assert(false);
 				break;
 		}
 	return std::make_pair(Axis(),0.0); // Failure
 }
 
 std::pair<Axis,double> MatrixElementClusterFissioner::sampleDirectionCluster(
 		const Lorentz5Momentum & pQ,
 		const Lorentz5Momentum & pClu)  const {
 	switch (_phaseSpaceSamplerCluster)
 	{
 		case 0:
 			{
 				// Aligned
 				Axis dir;
 				if (_covariantBoost)
 					// in Covariant Boost the positive z-Axis is defined as the direction of
 					// the pQ vector in the Cluster rest frame
 					dir = Axis(0,0,1);
 				else 
 					dir = sampleDirectionAligned(pQ, pClu);
 				return std::make_pair(dir,1.0);
 			}
 		case 1:
 			{
 				// Isotropic
 				return std::make_pair(sampleDirectionIsotropic(),1.0);
 			}
 		case 2:
 			{
 				// Tchannel
 				Energy M=pClu.mass();
 				// New
 				// double C_est_Tchannel=3.66;
 				// double power_est_Tchannel=-1.95;
 				// Old
 				double C_est_Tchannel=9.78;
 				double power_est_Tchannel=-2.5;
 				double A = C_est_Tchannel*pow(M/GeV,power_est_Tchannel);
 				double Ainv = 1.0/(1.0+A);
 				return sampleDirectionTchannel(sampleDirectionAligned(pQ,pClu),Ainv);
 			}
 		default:
 			assert(false);  
 	}
 	return std::make_pair(Axis(),0.0); // Failure
 }
 
 std::pair<Axis,double> MatrixElementClusterFissioner::sampleDirectionExponential(const Axis & dirQ, const double lambda) const {
 	Axis FinalDir = dirQ;
 	double cosTheta = Kinematics::sampleCosExp(lambda);
 	double phi;
 	// std::cout << "cosThetaSamp = "<< cosTheta <<"\tlambda = " <<lambda << std::endl;
 	// If no change in angle keep the direction fixed
 	if (fabs(cosTheta-1.0)>1e-14) {
 		// rotate to sampled angles
 		FinalDir.rotate(acos(cosTheta),dirQ.orthogonal());
 		phi  = UseRandom::rnd(-Constants::pi,Constants::pi);
 		FinalDir.rotate(phi,dirQ);
 	}
 	// std::cout << "cosThetaTrue = "<< FinalDir.cosTheta(dirQ) <<"\tlambda = " <<lambda << std::endl;
 	double weight = exp(lambda*(cosTheta-1.0));
 	if (std::isnan(weight) ||std::isinf(weight) )
 		std::cout << "lambda = " << lambda << "\t cos " << cosTheta<< std::endl;
 	assert(!std::isnan(weight));
 	assert(!std::isinf(weight));
 	if (fabs(FinalDir.cosTheta(dirQ)-cosTheta)>1e-8) std::cout << "cosThetaTrue = "<< FinalDir.cosTheta(dirQ) <<"\tlambda = " <<lambda << std::endl;
 	return std::make_pair(FinalDir,weight);
 }
 std::pair<Axis,double> MatrixElementClusterFissioner::sampleDirectionTchannel(const Axis & dirQ, const double Ainv) const {
 	double cosTheta = Kinematics::sampleCosTchannel(Ainv);
 	double phi;
 	Axis FinalDir = dirQ;
 	// If no change in angle keep the direction fixed
 	if (fabs(cosTheta-1.0)>1e-14) {
 		// rotate to sampled angles
 		FinalDir.rotate(acos(cosTheta),dirQ.orthogonal());
 		phi  = UseRandom::rnd(-Constants::pi,Constants::pi);
 		FinalDir.rotate(phi,dirQ);
 	}
 	double weight = 0.0;
 	if (1.0-Ainv>1e-10)
 		weight=1.0/pow(1.0/Ainv-cosTheta,2.0);
 	else
 		weight=1.0/pow((1.0-cosTheta)+(1.0-Ainv),2.0);
 	if (std::isnan(weight) ||std::isinf(weight) )
 		std::cout << "Ainv = " << Ainv << "\t cos " << cosTheta<< std::endl;
 	assert(!std::isnan(weight));
 	assert(!std::isinf(weight));
 	if (fabs(FinalDir.cosTheta(dirQ)-cosTheta)>1e-8) std::cout << "cosThetaTrue = "<< FinalDir.cosTheta(dirQ) <<"\tAinv = " <<Ainv << std::endl;
 	return std::make_pair(FinalDir,weight);
 }
 
 Axis MatrixElementClusterFissioner::sampleDirectionAligned(const Lorentz5Momentum & pQ, const Lorentz5Momentum & pClu) const {
 	Lorentz5Momentum pQinCOM(pQ);
 	pQinCOM.setMass(pQ.m());
 	pQinCOM.boost( -pClu.boostVector() );        // boost from LAB to C
 	return pQinCOM.vect().unit();
 }
 
 Axis MatrixElementClusterFissioner::sampleDirectionAlignedSmeared(const Lorentz5Momentum & pQ, const Lorentz5Momentum & pClu) const {
 	Lorentz5Momentum pQinCOM(pQ);
 	pQinCOM.setMass(pQ.m());
 	pQinCOM.boost( -pClu.boostVector() );        // boost from LAB to C
 	if (pQinCOM.vect().mag2()<=ZERO){
 		return sampleDirectionAlignedSmeared(pClu-pQ,pClu);
 	}
 	const Axis dir = pQinCOM.vect().unit();
 	double cluSmear = 0.5;
 	double cosTheta;
 	do {
 		cosTheta = 1.0 + cluSmear*log( UseRandom::rnd() );
 	} 
 	while (fabs(cosTheta)>1.0 || std::isnan(cosTheta) || std::isinf(cosTheta));
 
 	if (!(dir.mag2()>ZERO)){
 		std::cout << "\nDRI = 0"<< dir.mag2() << std::endl;
 	}
 	Axis dirSmeared = dir;
 	double phi;
 	if (fabs(cosTheta-1.0)>1e-10) {
 		// rotate to sampled angles
 		dirSmeared.rotate(acos(cosTheta),dir.orthogonal());
 		phi  = UseRandom::rnd(-M_PI,M_PI);
 		dirSmeared.rotate(phi,dir);
 	}
 	if (!(dirSmeared.mag2()>ZERO)){
 		std::cout << "\nDRI SMR = 0" <<cosTheta<< "\t" <<acos(cosTheta)<< "\t"<<  phi<< "\t"<< dirSmeared.mag2() << std::endl;
 		std::cout << dir.orthogonal() << std::endl;
 	}
 	return dirSmeared;
 }
 
 Axis MatrixElementClusterFissioner::sampleDirectionIsotropic() const {
   double cosTheta = -1 + 2.0 * UseRandom::rnd();
   double sinTheta = sqrt(1.0-cosTheta*cosTheta);
   double Phi = 2.0 * Constants::pi * UseRandom::rnd();
   Axis uClusterUniform(cos(Phi)*sinTheta, sin(Phi)*sinTheta, cosTheta);
   return uClusterUniform.unit();
 }
 
 Axis MatrixElementClusterFissioner::sampleDirectionSemiUniform(const Lorentz5Momentum & pQ, const Lorentz5Momentum & pClu) const {
   Axis dir = sampleDirectionAligned(pQ,pClu);
   Axis res;
   do {
 	  res=sampleDirectionIsotropic();
   }
   while (dir*res<0);
   return res;
 }
 namespace {
 	double SoftFunction(
 			const Lorentz5Momentum & pi,
 			const Lorentz5Momentum & pj,
 			const Lorentz5Momentum & q,
 			const Lorentz5Momentum & qbar) {
 		Energy2 mq2 = q*q;
 		Energy2 qqbar = q*qbar;
 		Energy2 piq = pi*q;
 		Energy2 piqbar = pi*qbar;
 		Energy2 pjq = pj*q;
 		Energy2 pjqbar = pj*qbar;
 		double numerator   = -(pi*pj)*(qqbar+mq2)/sqr(GeV2);
 		double denominator = sqr(qqbar+mq2)*(piq+piqbar)*(pjq+pjqbar)/sqr(GeV2*GeV2);
 		int cataniScheme = 1;
 		// Different expressions which should yield similar results
 		switch (cataniScheme) {
 			case 0:
 				numerator += ((piq)*(pjqbar) + (pjq)*(piqbar))/sqr(GeV2);
 				break;
 			case 1:
 				numerator += - (0.5*(piq-piqbar)*(pjq-pjqbar))/sqr(GeV2);
 				break;
 			default:
 				assert(false);
 		}
 		double Iij = numerator/denominator;
 		return Iij;
 	}
 }
 /* SQME for p1,p2->C1(q1,q),C2(q2,qbar) 
  * Note that:
  *      p0Q1  -> p1
  *      p0Q2  -> p2
  *      pQ1   -> q1
  *      pQone -> q
  *      pQ2   -> q2
  *      pQone -> qbar
  * */
 double MatrixElementClusterFissioner::calculateSQME(
 		const Lorentz5Momentum & p1,
 		const Lorentz5Momentum & p2,
 		const Lorentz5Momentum & q1,
 		const Lorentz5Momentum & q,
 		const Lorentz5Momentum & q2,
 		const Lorentz5Momentum & qbar) const {
 	double SQME;
 	switch (_matrixElement)
 	{
 		case 0:
 				SQME = 1.0;
 				break;
 		case 1:
 			{
 				/*
 				// Energy2 p1p2 = p1*p2;
 				Energy2 q1q2    = q1 * q2;
 				Energy2 q1q     = q1 * q ;
 				Energy2 q2qbar  = q2 * qbar;
 				Energy2 q2q     = q2 * q ;
 				Energy2 q1qbar  = q1 * qbar;
 				Energy2 qqbar   = q  * qbar;
 				Energy2 mq2 = q.mass2();
 				double Numerator = q1q2 * (qqbar + mq2)/sqr(GeV2);
 				Numerator += 0.5 * (q1q - q1qbar)*(q2q - q2qbar)/sqr(GeV2);
 				double Denominator = sqr(qqbar + mq2)*(q1q + q1qbar)*(q2q + q2qbar)/sqr(sqr(GeV2));
 				SQME = Numerator/Denominator;
 				*/
 				double I11 = SoftFunction(q1,q1,q,qbar);
 				double I22 = SoftFunction(q2,q2,q,qbar);
 				double I12 = SoftFunction(q1,q2,q,qbar);
 				SQME = (I11+I22-2.0*I12);
 				if (SQME<0.0) {
 					std::cout << "I11 = " << I11<< std::endl;
 					std::cout << "I22 = " << I22<< std::endl;
 					std::cout << "2*I12 = " << I12<< std::endl;
 					std::cout << "soft = " << I11+I22-2.0*I12<< std::endl;
 					std::cout << "M  = " << (p1+p2).m()/GeV<< std::endl;
 					std::cout << "M1 = " << (q1+q).m()/GeV<< std::endl;
 					std::cout << "M2 = " << (q2+qbar).m()/GeV<< std::endl;
 					std::cout << "m1 = " << (q1).m()/GeV<< std::endl;
 					std::cout << "m2 = " << (q2).m()/GeV<< std::endl;
 					std::cout << "m  = " << (q).m()/GeV<< std::endl;
 				}
 				break;
 			}
 		case 2:
 			{
 				/*
 				Energy2 p1p2    = p1 * p2;
 				Energy2 p1q     = p1 * q ;
 				Energy2 p2qbar  = p2 * qbar;
 				Energy2 p2q     = p2 * q ;
 				Energy2 p1qbar  = p1 * qbar;
 				Energy2 qqbar   = q  * qbar;
 				Energy2 mq2 = q.mass2();
 				double Numerator = p1p2 * (qqbar + mq2)/sqr(GeV2);
 				Numerator += 0.5 * (p1q - p1qbar)*(p2q - p2qbar)/sqr(GeV2);
 				double Denominator = sqr(qqbar + mq2)*(p1q + p1qbar)*(p2q + p2qbar)/sqr(sqr(GeV2));
 				SQME = Numerator/Denominator;
 				*/
 				double I11 = SoftFunction(p1,p1,q,qbar);
 				double I22 = SoftFunction(p2,p2,q,qbar);
 				double I12 = SoftFunction(p1,p2,q,qbar);
 				SQME = (I11+I22-2.0*I12);
 				if (SQME<0.0) {
 					std::cout << "I11 = " << I11<< std::endl;
 					std::cout << "I22 = " << I22<< std::endl;
 					std::cout << "2*I12 = " << I12<< std::endl;
 					std::cout << "soft = " << I11+I22-2.0*I12<< std::endl;
 					std::cout << "M  = " << (p1+p2).m()/GeV<< std::endl;
 					std::cout << "M1 = " << (q1+q).m()/GeV<< std::endl;
 					std::cout << "M2 = " << (q2+qbar).m()/GeV<< std::endl;
 					std::cout << "m1 = " << (q1).m()/GeV<< std::endl;
 					std::cout << "m2 = " << (q2).m()/GeV<< std::endl;
 					std::cout << "m  = " << (q).m()/GeV<< std::endl;
 				}
 				break;
 			}
 		case 4:
 			{
 				SQME = sqr(sqr(GeV2))/(sqr(q*qbar-q*q)*(p1*(q1+q)-p1*p1-sqrt((p1*p1)*(q*q)))*(p2*(q2+qbar)-p2*p2-sqrt((p2*p2)*(q*q))));
 				break;
 			}
 		case 5:
 			{
 				/*
 				Energy2 p1p2    = p1 * p2;
 				Energy2 p1q     = p1 * q ;
 				Energy2 p2qbar  = p2 * qbar;
 				Energy2 p2q     = p2 * q ;
 				Energy2 p1qbar  = p1 * qbar;
 				Energy2 qqbar   = q  * qbar;
 				Energy2 mq2 = q.mass2();
 				double Numerator = p1p2 * (qqbar + mq2)/sqr(GeV2);
 				Numerator += 0.5 * (p1q - p1qbar)*(p2q - p2qbar)/sqr(GeV2);
 				double Denominator = sqr(qqbar + mq2)*(p1q + p1qbar)*(p2q + p2qbar)/sqr(sqr(GeV2));
 				// add test Tchannel Matrix Element interference with gluon mass regulated
 				// Denominator *= sqr(sqr(p1-q1)-_epsilonResolution*sqrt((p1*p1)*(p2*p2)))/sqr(GeV2);
 				*/
 				static Energy mg=getParticleData(spectrum()->gluonId())->constituentMass();
 				double Denominator = (sqr(p1-q1)-_epsilonResolution*mg*mg)/(GeV2);
 				Denominator *= (sqr(p2-q2)-_epsilonResolution*mg*mg)/(GeV2);
 				double Numerator = ((q1*q2)*(p1*p2)+(p2*q1)*(p1*q2))/sqr(GeV2);
 				// double I11 = SoftFunction(p1,p1,q,qbar);
 				// double I22 = SoftFunction(p2,p2,q,qbar);
 				// double I12 = SoftFunction(p1,p2,q,qbar);
 				double I11 = SoftFunction(q1,q1,q,qbar);
 				double I22 = SoftFunction(q2,q2,q,qbar);
 				double I12 = SoftFunction(q1,q2,q,qbar);
 				SQME = Numerator*(I11+I22-2.0*I12)/Denominator;
 				if (SQME<0.0) {
 					std::cout << "I11 = " << I11<< std::endl;
 					std::cout << "I22 = " << I22<< std::endl;
 					std::cout << "2*I12 = " << I12<< std::endl;
 					std::cout << "soft = " << I11+I22-2.0*I12<< std::endl;
 					std::cout << "Numerator = " << Numerator<< std::endl;
 					std::cout << "Denominator = " << Denominator<< std::endl;
 					std::cout << "M  = " << (p1+p2).m()/GeV<< std::endl;
 					std::cout << "M1 = " << (q1+q).m()/GeV<< std::endl;
 					std::cout << "M2 = " << (q2+qbar).m()/GeV<< std::endl;
 					std::cout << "m1 = " << (q1).m()/GeV<< std::endl;
 					std::cout << "m2 = " << (q2).m()/GeV<< std::endl;
 					std::cout << "m  = " << (q).m()/GeV<< std::endl;
 				}
 				break;
 			}
 		default:
 			assert(false);
 	}
 	if (SQME < 0) throw	Exception()
 		<< "Squared Matrix Element = "<< SQME <<" < 0 in MatrixElementClusterFissioner::calculateSQME() "
 		<< Exception::runerror;
 	return SQME;
 }
 /* Overestimate for SQME for p1,p2->C1(q1,q),C2(q2,qbar) 
  * Note that:
  *      p0Q1  -> p1   where Mass -> m1
  *      p0Q2  -> p2   where Mass -> m2
  *      pQ1   -> q1   where Mass -> m1
  *      pQone -> q    where Mass -> mq
  *      pQ2   -> q2   where Mass -> m2
  *      pQone -> qbar where Mass -> mq
  * */
 double MatrixElementClusterFissioner::calculateSQME_OverEstimate(
 		const Energy& Mc,
 		const Energy& m1,
 		const Energy& m2,
 		const Energy& mq
 		) const {
 	double SQME_OverEstimate;
 	switch (_matrixElement)
 	{
 		case 0:
 				SQME_OverEstimate = 1.0;
 				break;
 		case 1:
 			{
 				// Fit factor for guess of best overestimate
 				double A = 0.25;
 				SQME_OverEstimate = _safetyFactorMatrixElement*A*pow(mq/GeV,-4);
 				break;
 			}
 		case 2:
 			{
 				// Fit factor for guess of best overestimate
 				double A = 0.25;
 				SQME_OverEstimate = _safetyFactorMatrixElement*A*pow(mq/GeV,-4);
 				break;
 			}
 		case 4:
 			{
 				// Fit factor for guess of best overestimate
 				SQME_OverEstimate = _safetyFactorMatrixElement*sqr(sqr(GeV2))/(sqr(mq*mq)*m1*m2*(m1+mq)*(m2+mq));
 				break;
 			}
 		case 5:
 			{
 				// Fit factor for guess of best overestimate
 				// Energy MassMax = 8.550986578849006037e+00*GeV; // mass max of python
 				// double wTotMax = 5.280507222727160297e+03; // at MassMax
 				// double argExp = 55.811; // from fit of python package
 				// double powLog = 0.08788; // from fit of python package
 
-				static Energy MassMax = 5.498037126562503119e+01*GeV; // mass max of python
-				static double wTotMax = 1.570045806367627112e+06; // at MassMax
-				static double argExp = 16.12; // from fit of python package
-				static double powLog = 0.3122; // from fit of python package
+				// Old
+				// static Energy MassMax = 5.498037126562503119e+01*GeV; // mass max of python
+				// static const double wTotMax = 1.570045806367627112e+06; // at MassMax
+				// static const double argExp = 16.12; // from fit of python package
+				// static const double powLog = 0.3122; // from fit of python package
+				// New fits from python package (most effective for all masses m_ud)
+				static Energy MassMax = 1.072117239679688225e+02*GeV; // mass max of python
+				static const double wTotMax = 6.572201964467836914e+11; // at MassMax
+				static const double argExp = 1.216961110145260250e+01; // from fit of python package
+				static const double powLog = 6.437455646293682721e-01; // from fit of python package
 				// Energy2 p1p2=0.5*(Mc*Mc-m1*m1-m2*m2);
 				// SQME_OverEstimate = _safetyFactorMatrixElement*A*pow(mq/GeV,-4)*(2*sqr(p1p2))/sqr(_epsilonResolution*(m1*m2));
 				Energy Mmin = (m1+m2+2*mq);
 				// Energy MdblPrec = Mmin*exp(pow(pow(log(MassMax/Mmin),powLog)+600.0/argExp,1.0/powLog));
 				// if (Mc >MdblPrec)
 					// std::cout << "errroRRRRR R MC = " << Mc/GeV << "\t Mcmax "<< MdblPrec/GeV<< std::endl;
 				if (MassMax<Mmin) MassMax=Mmin;
 				double Overestimate = wTotMax*exp(argExp*(pow(log(Mc/Mmin),powLog)-pow(log(MassMax/Mmin),powLog)));
 				SQME_OverEstimate = _safetyFactorMatrixElement*Overestimate;//*A*pow(mq/GeV,-4)*(2*sqr(p1p2))/sqr(_epsilonResolution*(m1*m2));
 				if (SQME_OverEstimate==0 || std::isinf(SQME_OverEstimate)|| std::isnan(SQME_OverEstimate)) {
 					std::cout << "SQME_OverEstimate is " << SQME_OverEstimate << std::endl;
 					std::cout << "Overestimate is " << Overestimate << std::endl;
 					std::cout << "MC " << Mc/GeV << std::endl;
 					std::cout << "m " << mq/GeV << std::endl;
 					std::cout << "m1 " << m1/GeV << std::endl;
 					std::cout << "m2 " << m2/GeV << std::endl;
 				}
 				break;
 			}
 		default:
 			assert(false);
 	}
 	return SQME_OverEstimate;
 }
 
 double MatrixElementClusterFissioner::drawKinematics(
              const Lorentz5Momentum & pClu,
 					   const Lorentz5Momentum & p0Q1,
 					   const Lorentz5Momentum & p0Q2,
 					   const bool toHadron1,
 					   const bool toHadron2,
 					   Lorentz5Momentum & pClu1,
 					   Lorentz5Momentum & pClu2,
 					   Lorentz5Momentum & pQ1,
 					   Lorentz5Momentum & pQbar,
 					   Lorentz5Momentum & pQ,
 					   Lorentz5Momentum & pQ2bar) const {
 	double weightTotal=0.0;
   if (pClu.mass() < pClu1.mass() + pClu2.mass()
 		  || pClu1.mass()<ZERO
 		  || pClu2.mass()<ZERO  ) {
     throw Exception() << "Impossible Kinematics in MatrixElementClusterFissioner::drawKinematics() (A)\n"
 					<< "Mc  = "<< pClu.mass()/GeV <<" GeV\n"
 					<< "Mc1 = "<< pClu1.mass()/GeV <<" GeV\n"
 					<< "Mc2 = "<< pClu2.mass()/GeV <<" GeV\n"
 		      << Exception::eventerror;
   }
 
 	// Sample direction of the daughter clusters
 	std::pair<Axis,double> directionCluster = sampleDirectionCluster(p0Q1, pClu);
 	Axis DirToClu = directionCluster.first;
 	weightTotal   = directionCluster.second;
 	if (0 && _writeOut) {
 		ofstream out("WriteOut/test_Cluster.dat",std::ios::app);
 		Lorentz5Momentum pQinCOM(p0Q1);
 		pQinCOM.setMass(p0Q1.m());
 		pQinCOM.boost( -pClu.boostVector() );        // boost from LAB to C
 		out << DirToClu.cosTheta(pQinCOM.vect()) << "\n";
 	}
 	if (_covariantBoost) {
 		const Energy M  = pClu.mass();
 		const Energy M1 = pClu1.mass();
 		const Energy M2 = pClu2.mass();
 		const Energy PcomClu=Kinematics::pstarTwoBodyDecay(M,M1,M2);
 		Momentum3 pClu1sampVect( PcomClu*DirToClu);
 		Momentum3 pClu2sampVect(-PcomClu*DirToClu);
 		pClu1.setMass(M1);
 		pClu1.setVect(pClu1sampVect);
 		pClu1.rescaleEnergy();
 		pClu2.setMass(M2);
 		pClu2.setVect(pClu2sampVect);
 		pClu2.rescaleEnergy();
 	}
 	else {
 		Lorentz5Momentum pClutmp(pClu);
 		pClutmp.boost(-pClu.boostVector());
 		Kinematics::twoBodyDecay(pClutmp, pClu1.mass(), pClu2.mass(),DirToClu, pClu1, pClu2);
 	}
 	// In the case that cluster1 does not decay immediately into a single hadron,
 	// calculate the momenta of Q1 (as constituent of C1) and Qbar in the
 	// (parent) C1 frame first, where the direction of Q1 is u.vect().unit(),
 	// and then boost back in the LAB frame.
 	if(!toHadron1) {
 		if (pClu1.m() < pQ1.mass() + pQbar.mass() ) {
 			throw Exception() << "Impossible Kinematics in MatrixElementClusterFissioner::drawKinematics() (B)"
 				<< Exception::eventerror;
 		}
 		std::pair<Axis,double> direction1 = sampleDirectionConstituents(pClu1,pClu.mass());
 		// Need to boost constituents first into the pClu rest frame
 		//  boost from Cluster1 rest frame to Cluster COM Frame
 		// Kinematics::twoBodyDecay(pClu1, pQ1.mass(), pQbar.mass(), DirClu1, pQ1, pQbar);
 		Kinematics::twoBodyDecay(pClu1, pQ1.mass(), pQbar.mass(), direction1.first, pQ1, pQbar);
 		weightTotal*=direction1.second;
 		if (0 && _writeOut) {
 			ofstream out("WriteOut/test_Constituents1.dat",std::ios::app);
 			Lorentz5Momentum pQ1inCOM(pQ1);
 			pQ1inCOM.setMass(pQ1.m());
 			pQ1inCOM.boost( -pClu1.boostVector() );        // boost from LAB to C
 			out << pQ1inCOM.vect().cosTheta(pClu1.vect()) << "\n";
 		}
 	}
 
 	// In the case that cluster2 does not decay immediately into a single hadron,
 	// Calculate the momenta of Q and Q2bar (as constituent of C2) in the
 	// (parent) C2 frame first, where the direction of Q is u.vect().unit(),
 	// and then boost back in the LAB frame.
 	if(!toHadron2) {
 		if (pClu2.m() < pQ.mass() + pQ2bar.mass() ) {
 			throw Exception() << "Impossible Kinematics in MatrixElementClusterFissioner::drawKinematics() (C)"
 				<< Exception::eventerror;
 		}
 		std::pair<Axis,double> direction2 = sampleDirectionConstituents(pClu2,pClu.mass());
 		//  boost from Cluster2 rest frame to Cluster COM Frame 
 		Kinematics::twoBodyDecay(pClu2, pQ2bar.mass(), pQ.mass(), direction2.first, pQ2bar, pQ);
 		weightTotal*=direction2.second;
 		if (0 && _writeOut) {
 			ofstream out("WriteOut/test_Constituents2.dat",std::ios::app);
 			Lorentz5Momentum pQ2inCOM(pQ2bar);
 			pQ2inCOM.setMass(pQ2bar.m());
 			pQ2inCOM.boost( -pClu2.boostVector() );        // boost from LAB to C
 			out << pQ2inCOM.vect().cosTheta(pClu2.vect()) << "\n";
 		}
 	}
 	// Boost all momenta from the Cluster COM frame to the Lab frame
 	if (_covariantBoost) {
 			std::vector<Lorentz5Momentum *> momenta;
 			momenta.push_back(&pClu1);
 			momenta.push_back(&pClu2);
 			if (!toHadron1) {
 				momenta.push_back(&pQ1);
 				momenta.push_back(&pQbar);
 			}
 			if (!toHadron2) {
 				momenta.push_back(&pQ);
 				momenta.push_back(&pQ2bar);
 			}
 			Kinematics::BoostIntoTwoParticleFrame(pClu.mass(),p0Q1, p0Q2, momenta);
 	}
 	else {
 		pClu1.boost(pClu.boostVector());
 		pClu2.boost(pClu.boostVector());
 		pQ1.boost(pClu.boostVector());
 		pQ2bar.boost(pClu.boostVector());
 		pQ.boost(pClu.boostVector());
 		pQbar.boost(pClu.boostVector());
 	}
 	return weightTotal; // success
 }