diff --git a/Hadronization/Ropewalk.cc b/Hadronization/Ropewalk.cc
--- a/Hadronization/Ropewalk.cc
+++ b/Hadronization/Ropewalk.cc
@@ -1,1259 +1,1261 @@
 // -*- C++ -*-
 //
 // This is the implementation of the non-inlined, non-templated member
 // functions of the Ropewalk class.
 //
 
 #include "Ropewalk.h"
 #include "ThePEG/Interface/ClassDocumentation.h"
 #include "ThePEG/EventRecord/Particle.h"
 #include "ThePEG/EventRecord/Step.h"
 #include "ThePEG/Repository/UseRandom.h"
 #include "ThePEG/Repository/CurrentGenerator.h"
 #include "ThePEG/PDT/EnumParticles.h"
 #include "ThePEG/Utilities/Selector.h"
 #include "ThePEG/Utilities/SimplePhaseSpace.h"
 #include "ThePEG/Utilities/UtilityBase.h"
 #include "ThePEG/Utilities/Throw.h"
 #include "ThePEG/Handlers/StepHandler.h"
 
 
 
 using namespace TheP8I;
 
 Ropewalk::Ropewalk(const vector<ColourSinglet> & singlets, Length width,
 		   Energy scale, double jDP, bool throwaway, bool shoving, double rcIn, 
 		   StringTension gaIn, double geIn, double ycIn, double dyIn, Length tsIn, Length dtIn,
 		   bool lorentzIn, bool cylinderIn, Energy pTcutIn, double mstringyIn, bool longSoftIn,
 		   HistKeeper* hk, bool deb) 
   : R0(width), m0(scale), junctionDiquarkProb(jDP), rCutOff(rcIn*width), gAmplitude(gaIn),
      gExponent(geIn), yCutOff(ycIn), deltay(dyIn), tshove(tsIn), deltat(dtIn), lorentz(lorentzIn),
 	cylinderShove(cylinderIn), stringpTCut(pTcutIn), minStringy(mstringyIn), longSoft(longSoftIn),
        	hkPtr(hk), debug(deb), strl0(0.0), strl(0.0), avh(0.0), avp(0.0), avq(0.0) {
   for ( int is = 0, Ns = singlets.size(); is < Ns; ++is ){
  	if(!longSoft)
 		stringdipoles[cloneToFinal(singlets[is])];
 	else{
 		tcPVector pVec = singlets[is].partons();
         	double maxrap = 0;
         	double minrap = 0;
         	Energy pTmax = 0*GeV;
  		for(int id = 0, Nd = int(pVec.size()); id < Nd; ++id){
         	        double y = pVec[id]->rapidity();
         	        Energy pT = pVec[id]->momentum().perp();
         	        if(id == 0){
 		               maxrap = y;
 		  	       minrap = y;
 		               pTmax = pT;
 			}
 			else{
         	               if(pTmax < pT)
 		                    pTmax = pT;
 			       if(maxrap < y)
 				       maxrap = y;
 			       if(minrap > y)
 				       minrap = y;
         	        }       
         
 		}
 	 	if(hkPtr){
 		        hkPtr->hist("stringlength")->fill(maxrap-minrap,hkPtr->currentWeight());
 		        hkPtr->hist("stringptMax")->fill(pTmax/GeV,hkPtr->currentWeight());
 		   	if(maxrap - minrap > minStringy)	
 		       		hkPtr->hist("stringpTMaxCut")->fill(pTmax/GeV,hkPtr->currentWeight());
 	       	}
 	if(maxrap-minrap > minStringy && pTmax < stringpTCut)
 		stringdipoles[cloneToFinal(singlets[is])];
 	else
 		spectatorDipoles[cloneToFinal(singlets[is])];
 	}
   }
   getDipoles();
   calculateOverlaps(false);
   if(throwaway) 
 	 doBreakups();
   lambdaBefore = lambdaSum();
   if ( debug ) CurrentGenerator::log() << singlets.size() << "s "
 				       << dipoles.size() << "d ";
   if(hkPtr){
 	  for(DipoleMap::iterator itr = stringdipoles.begin(); itr!=stringdipoles.end();++itr){
 	  	vector<Dipole*> dips = itr->second;
 		for(int id = 0, Nd = dips.size(); id < Nd; ++id){
 			Dipole* d = dips[id];
 			LorentzMomentum mpa = d->pa->momentum();
 			LorentzMomentum mpc = d->pc->momentum();
 		
 		LorentzMomentum mpaRot = (d->R)*mpa;
 			LorentzMomentum mpcRot = (d->R)*mpc;
 			if(d->pa->id() == 21){
 				hk->hist("normalGluonPt")->fill(mpa.perp()/GeV,
 						hk->currentWeight());
 				hk->hist("normalGluonRestFramePt")->fill(
 						mpaRot.perp()/GeV,hk->currentWeight());
 			}
 			if(abs(d->pa->id()) < 10 ){
 				hk->hist("normalQuarkPt")->fill(mpa.perp()/GeV,
 						hk->currentWeight());
 				hk->hist("normalQuarkRestFramePt")->fill(
 						mpaRot.perp()/GeV,hk->currentWeight());
 			}
 			if(abs(d->pc->id()) < 10 ){
 				hk->hist("normalQuarkPt")->fill(mpc.perp()/GeV,
 						hk->currentWeight());
 				hk->hist("normalQuarkRestFramePt")->fill(
 						mpcRot.perp()/GeV,hk->currentWeight());
 			}
 			if(abs(d->pc->id()) > 100 ){
 				hk->hist("normalDiQuarkPt")->fill(mpc.perp()/GeV,
 						hk->currentWeight());
 				hk->hist("normalDiQuarkRestFramePt")->fill(
 						mpcRot.perp()/GeV,hk->currentWeight());
 			}
 			if(abs(d->pa->id()) > 100 ){
 				hk->hist("normalDiQuarkPt")->fill(mpa.perp()/GeV,
 						hk->currentWeight());
 				hk->hist("normalDiQuarkRestFramePt")->fill(
 						mpaRot.perp()/GeV,hk->currentWeight());
 			}
 		}
 	  }
   
   
   }
   
   if(shoving){
   	  shoveTheDipoles();
 	  // update color singlets
   	  DipoleMap newStringDipoles;
 
 	  for(DipoleMap::iterator itr = stringdipoles.begin(); itr != stringdipoles.end(); ++itr){
 
 		delete itr->first;
 	        // The old dipoles
 		vector<Dipole*> oldDipoles = itr->second;	
 	  	tcParticleSet updatedParticles;
 			
 		for(int id = 0, Nd = oldDipoles.size(); id < Nd; ++id){
 	  		Dipole* d = oldDipoles[id];
 			const ParticleVector children = d->pa->children();
 			if(children.empty())
 				updatedParticles.insert(d->pa);
 			for(int ic = 0, Nc = children.size(); ic < Nc; ++ic)
 				updatedParticles.insert(children[ic]);
 			if(d->pc->id() != 21){
 				const ParticleVector children = d->pc->children();
 				if(children.empty())
 					updatedParticles.insert(d->pc);
 				for(int ic = 0, Nc = children.size(); ic < Nc; ++ic)
 					updatedParticles.insert(children[ic]);
 			}
   		}
 		
 
 		tcPPtr p = *updatedParticles.begin();
 		if(p->colourLine())
 			newStringDipoles[new ColourSinglet(p->colourLine(), updatedParticles)];
 		else if(p->antiColourLine())
 			newStringDipoles[new ColourSinglet(p->antiColourLine(), updatedParticles)];
 		else
 			Throw<ColourException>()
 				<< "Updating colour singlets after shoving failed."
 				<< "This is a serious error, please contact the authors."
 				<< Exception::abortnow;
 	  
 	  }
 	  stringdipoles = newStringDipoles;
   	  getDipoles();
 	  calculateOverlaps(false);
 	   if(hkPtr){
 	  for(DipoleMap::iterator itr = stringdipoles.begin(); itr!=stringdipoles.end();++itr){
 	  	vector<Dipole*> dips = itr->second;
 		for(int id = 0, Nd = dips.size(); id < Nd; ++id){
 			Dipole* d = dips[id];
 			LorentzMomentum mpa = d->pa->momentum();
 			LorentzMomentum mpc = d->pc->momentum();
 			LorentzMomentum mpaRot = (d->R)*mpa;
 			LorentzMomentum mpcRot = (d->R)*mpc;
 			if(d->pa->id() == 21){
 				hk->hist("excitedEndGluonPt")->fill(mpa.perp()/GeV,
 						hk->currentWeight());
 				hk->hist("excitedEndGluonRestFramePt")->fill(
 						mpaRot.perp()/GeV,hk->currentWeight());
 			}
 			if(abs(d->pa->id()) < 10 ){
 				hk->hist("excitedQuarkPt")->fill(mpa.perp()/GeV,
 						hk->currentWeight());
 				hk->hist("excitedQuarkRestFramePt")->fill(
 						mpaRot.perp()/GeV,hk->currentWeight());
 			}
 			if(abs(d->pc->id()) < 10 ){
 				hk->hist("excitedQuarkPt")->fill(mpc.perp()/GeV,
 						hk->currentWeight());
 				hk->hist("excitedQuarkRestFramePt")->fill(
 						mpcRot.perp()/GeV,hk->currentWeight());
 			}
 			if(abs(d->pc->id()) > 100 ){
 				hk->hist("excitedDiQuarkPt")->fill(mpc.perp()/GeV,
 						hk->currentWeight());
 				hk->hist("excitedDiQuarkRestFramePt")->fill(
 						mpcRot.perp()/GeV,hk->currentWeight());
 			}
 			if(abs(d->pa->id()) > 100 ){
 				hk->hist("excitedDiQuarkPt")->fill(mpa.perp()/GeV,
 						hk->currentWeight());
 				hk->hist("excitedDiQuarkRestFramePt")->fill(
 						mpaRot.perp()/GeV,hk->currentWeight());
 			}
 		}
 	  }
   
   
   }
 
   	}
   }
 
 Ropewalk::~Ropewalk() {
   for ( DipoleMap::iterator it = stringdipoles.begin();
 	it != stringdipoles.end(); ++it ) delete it->first;
 }
 
 
 ColourSinglet * Ropewalk::cloneToFinal(const ColourSinglet & cs) {
   tcParticleSet final;
   for ( int i = 0, N = cs.partons().size(); i < N; ++i )
     final.insert(cs.partons()[i]->final());
   tcPPtr p = *final.begin();
   if(hkPtr){
 	  hkPtr->hist("nPartons")->fill(final.size(), hkPtr->currentWeight());
   }
   if ( p->colourLine() ) return new ColourSinglet(p->colourLine(), final);
   if ( p->antiColourLine() ) return new ColourSinglet(p->antiColourLine(), final);
   Throw<ColourException>()
     << "Cloning ColourSinglets failed in Ropewalk. "
     << "This is a serious error - please contact the authors."
     << Exception::abortnow;
   return 0;
 }
 
 LorentzPoint Ropewalk::
 propagate(const LorentzPoint & b, const LorentzMomentum & p) const {
   return b + p/(p.e()*m0/hbarc);
   //  return b;
 }
 
 void Ropewalk::getDipoles() {
   dipoles.clear();
   // First extract all dipoles from all strings (pieces).
   for ( DipoleMap::iterator it = stringdipoles.begin();
 	it != stringdipoles.end(); ++it ) {
     ColourSinglet & string = *it->first;
     for ( int isp = 1, Nsp = string.nPieces(); isp <= Nsp; ++isp ) {
       const ColourSinglet::StringPiece & sp = string.piece(isp);
       if ( sp.size() < 2 ) continue;
       bool forward = sp[0]->colourLine() &&
 	sp[0]->colourLine() == sp[1]->antiColourLine();
       for ( int i = 0, N = sp.size(); i < (N - 1); ++i ) {
 	if ( forward )
 	  dipoles.push_back(Dipole(sp[i], sp[i + 1], string, m0));
 	else
 	  dipoles.push_back(Dipole(sp[i + 1], sp[i], string, m0));
       }
       if ( !forward && sp.front()->colourLine() &&
 	   sp.front()->colourLine() == sp.back()->antiColourLine() )
 	dipoles.push_back(Dipole(sp.front(), sp.back(), string, m0));
       else if ( forward && sp.front()->antiColourLine() &&
 		sp.front()->antiColourLine() == sp.back()->colourLine() )
 	dipoles.push_back(Dipole(sp.back(), sp.front(), string, m0));
     }
   }
 
   for ( int i = 0, N = dipoles.size(); i < N; ++i ) {
     stringdipoles[dipoles[i].string].push_back(&dipoles[i]);
     strl0 += dipoles[i].yspan(1.0*GeV);
   }
 
 }
 
 double Ropewalk::limitrap(const LorentzMomentum & p) const {
   if ( p.z() == ZERO ) return 0.0;
   Energy mt = sqrt(max(p.perp2() + p.m2(), sqr(m0)));
   double rap = log((p.t() + abs(p.z()))/mt);
   return p.z() > ZERO? rap: -rap;
 } 
 
 Ropewalk::OverlappingDipole::
 OverlappingDipole(const Dipole & d, const LorentzRotation R, const Ropewalk * rw)
   : dipole(&d), dir(1) {
   // Get the boost to other dipole's rest frame and calculate
   // rapidities.
   bc = R*rw->propagate(d.pc->vertex(), d.pc->momentum());
   ba = R*rw->propagate(d.pa->vertex(), d.pa->momentum());
   yc = rw->limitrap(R*d.pc->momentum());
   ya = rw->limitrap(R*d.pa->momentum());
   if ( yc < ya ) dir = -1;
 }
 
 
 
 
 void Ropewalk::calculateOverlaps(bool doPropagate) {
 
   // Then calculate all overlaps between pairs of dipoles.
   for ( int i1 = 0, Nd = dipoles.size(); i1 < Nd; ++i1 ) {
     Dipole & d1 = dipoles[i1];
     d1.clear();
     if ( d1.s() <= sqr(m0) ) continue;
     // Get the boost to dipoles rest frame and calculate rapidities.
     LorentzMomentum pc1 = d1.pc->momentum();
     LorentzMomentum pa1 = d1.pa->momentum();
     //LorentzRotation R = Utilities::boostToCM(make_pair(&pc1, &pa1));
     if(doPropagate){
     	d1.bc = d1.R*propagate(d1.pc->vertex(), d1.pc->momentum());
     	d1.ba = d1.R*propagate(d1.pa->vertex(), d1.pa->momentum());
     }
     else{
     	d1.bc = d1.pc->vertex();
 	d1.ba = d1.pa->vertex();
     }
     double yc1 = limitrap(pc1);
     double ya1 = limitrap(pa1);
     double n = 0.0;
     double m = 0.0;
     if ( yc1 <= ya1 ) continue; // don't care about too small strings.
     for ( int i2 = 0; i2 < Nd; ++i2 ) {
       if ( i1 == i2 ) continue;
       // Boost to the rest frame of dipole 1.
       if ( dipoles[i2].s() <= sqr(m0) ) continue;
       OverlappingDipole od(dipoles[i2], d1.R, this);
       // Ignore if not overlapping in rapidity.
       if ( min(od.yc, od.ya) > yc1 || max(od.yc, od.ya) < ya1 || od.yc == od.ya )
 	continue;
       // Calculate rapidity overlap.
       double yomax = min(max(od.yc, od.ya), yc1);
       double yomin = max(min(od.yc, od.ya), ya1);
       // Sample a random point in the rapidity overlap region and get
       // positions in space and check overlap.
       double yfrac = (yomax - yomin)/(yc1 - ya1);
       double y = UseRandom::rnd(yomin, yomax);
       if ( !od.overlap(y, d1.ba + (d1.bc - d1.ba)*(y - ya1)/(yc1 - ya1), R0) )
 	yfrac = 0.0;
       // Sum overlaps.
       if ( od.dir > 0 ) {
 	n += yfrac;
       } else {
 	m += yfrac;
       }
       od.yfrac = yfrac*od.dir;
       d1.overlaps.push_back(od);
     }
     d1.n = int(n + UseRandom::rnd());
     d1.m = int(m + UseRandom::rnd());
     d1.initWeightMultiplet();
     avp += d1.p*d1.yspan(1.0*GeV);
     avq += d1.q*d1.yspan(1.0*GeV);
   } 
 }
 
 double Ropewalk::Dipole::reinit(double ry, Length R0, Energy m0) {
   // First calculate the rapidity in this restframe.
   double y = yspan(m0)*(ry - 0.5);
   // Then get the position in space of the string at this rapidity.
   LorentzPoint b = ba + (bc - ba)*ry;
   p = 1;
   q = 0;
   // Now go through all overlapping dipoles.
   for ( int i = 0, N = overlaps.size(); i < N; ++i ) {
     if ( overlaps[i].dipole->broken ) continue;
     if( overlaps[i].dipole->hadr ) continue;
     if ( overlaps[i].overlap(y, b, R0) ) {
       if ( overlaps[i].dir > 0 ) ++p;
       else ++q;
     }
   }
   return kappaEnhancement();
 } 
 
 void Ropewalk::Dipole::initMultiplet() {
   typedef pair<int,int> Plet;
 
   int ns = 0;
   int ms = 0;
   while ( ns < n || ms < m ) {
     Plet diff;
     double octetveto = double(ns + ms + 1 - p - q)/double(ns + ms + 1);
     if ( double(n - ns) > UseRandom::rnd()*double(n + m - ns - ms) ) {
       Selector<Plet> sel;
       sel.insert(multiplicity(p + 1, q), Plet(1, 0));
       sel.insert(multiplicity(p, q - 1)*octetveto, Plet(0, -1));
       sel.insert(multiplicity(p - 1, q + 1), Plet(-1, 1));
       diff = sel[UseRandom::rnd()];
       ++ns;
     } else {
       Selector<Plet> sel;
       sel.insert(multiplicity(p, q + 1), Plet(0, 1));
       sel.insert(multiplicity(p - 1, q)*octetveto, Plet(-1, 0));
       sel.insert(multiplicity(p + 1, q - 1), Plet(1, -1));
       diff = sel[UseRandom::rnd()];
       ++ms;
     }
     if ( diff.first == -diff.second ) nb++;
     p += diff.first;
     q += diff.second;
   }
   /* *** ATTENTION *** maybe better if Christian implements this */
 
 }
 
 void Ropewalk::Dipole::initNewMultiplet() {
   typedef pair<int,int> Plet;
 
   int ns = 0;
   int ms = 0;
   for ( int i = 0, N = overlaps.size(); i < N; ++i ) {
     if ( abs(overlaps[i].yfrac) <  UseRandom::rnd() ) continue;
     Plet diff(0,0);
     double octetveto = double(ns + ms + 1 - p - q)/double(ns + ms + 1);
     if ( overlaps[i].dir > 0 ) {
       Selector<Plet> sel;
       sel.insert(multiplicity(p + 1, q), Plet(1, 0));
       sel.insert(multiplicity(p, q - 1)*octetveto, Plet(0, -1));
       sel.insert(multiplicity(p - 1, q + 1), Plet(-1, 1));
       diff = sel[UseRandom::rnd()];
       ++ns;
     } else {
       Selector<Plet> sel;
       sel.insert(multiplicity(p, q + 1), Plet(0, 1));
       sel.insert(multiplicity(p - 1, q)*octetveto, Plet(-1, 0));
       sel.insert(multiplicity(p + 1, q - 1), Plet(1, -1));
       diff = sel[UseRandom::rnd()];
       ++ms;
     }
     if ( diff.first == -diff.second ) nb++;
     p += diff.first;
     q += diff.second;
   }
   n = ns;
   m = ms;
   /* *** ATTENTION *** maybe better if Christian implements this */
 
 }
 
 void Ropewalk::Dipole::initWeightMultiplet() {
   typedef pair<int,int> Plet;
 
   int ns = 0;
   int ms = 0;
   double mab = sqrt(s())/GeV;
   for ( int i = 0, N = overlaps.size(); i < N; ++i ) {
     if ( abs(overlaps[i].yfrac) <  UseRandom::rnd() ) continue;
     const Dipole * od = overlaps[i].dipole;
     double mcd = sqrt(od->s())/GeV;
     double w8 = 1.0/sqr(mab*mcd); //The weight for 3 + 3bar -> 8
     double w6 = w8; // The weight for 3 + 3 -> 6
     Plet diff(0,0);
     double octetveto = double(ns + ms + 1 - p - q)/double(ns + ms + 1);
     if ( overlaps[i].dir > 0 ) {
       double mac = (pc->momentum() + od->pc->momentum()).m()/GeV;
       double mbd = (pa->momentum() + od->pa->momentum()).m()/GeV;
       double w1 = octetveto/sqr(mac*mbd); // The weight for 3 + 3bar -> 1
       double w3 = 1.0/(mab*mcd*mac*mbd); //The weight for 3 + 3 -> 3bar
       Selector<Plet> sel;
       sel.insert(multiplicity(p + 1, q) +
 		 multiplicity(p, q - 1)*w8/(w8 + w1) +
 		 multiplicity(p - 1, q + 1)*w6/(w6 + w3), Plet(1, 0));
       sel.insert(multiplicity(p, q - 1)*w1/(w1 + w8), Plet(0, -1));
       sel.insert(multiplicity(p - 1, q + 1)*w3/(w3 + w6), Plet(-1, 1));
       diff = sel[UseRandom::rnd()];
       ++ns;
     } else {
       double mac = (pa->momentum() + od->pc->momentum()).m()/GeV;
       double mbd = (pc->momentum() + od->pa->momentum()).m()/GeV;
       if ( mac*mbd <= 0.0 ) { 
 	++q; ++ms;
 	continue;
       }
       double w1 = octetveto/sqr(mac*mbd); // The weight for 3 + 3bar -> 1
       double w3 = 1.0/(mab*mcd*mac*mbd); //The weight for 3 + 3 -> 3bar
       Selector<Plet> sel;
       sel.insert(multiplicity(p, q + 1) +
 		 multiplicity(p - 1, q)*w8/(w8 + w1) +
 		 multiplicity(p + 1, q - 1)*w6/(w6 + w3), Plet(0, 1));
       sel.insert(multiplicity(p - 1, q)*w1/(w1 + w8), Plet(-1, 0));
       sel.insert(multiplicity(p + 1, q - 1)*w3/(w3 + w6), Plet(1, -1));
       diff = sel[UseRandom::rnd()];
       ++ms;
     }
     if ( diff.first == -diff.second ) nb++;
     p += diff.first;
     q += diff.second;
   }
   n = ns;
   m = ms;
   /* *** ATTENTION *** maybe better if Christian implements this */
 
 }
 
 double Ropewalk::getNb(){
   double nba = 0;
    for ( int i = 0, N = dipoles.size(); i < N; ++i ){
      nba += double(dipoles[i].nb);
      //cout << dipoles[i].n << " " << dipoles[i].m << " " << dipoles[i].p << " " << dipoles[i].q << endl;
      //cout << double(dipoles[i].n + dipoles[i].m + 1 - dipoles[i].p - dipoles[i].q) << endl;
      //cout << " --- " << endl;  
      //nba += double(dipoles[i].n + dipoles[i].m + 1 - dipoles[i].p - dipoles[i].q);
   }
    // cout << nba << endl;
    return nba;
 }
 
 double Ropewalk::getkW(){
     double kw = 0;
      for ( int i = 0, N = dipoles.size(); i < N; ++i )
        kw += dipoles[i].kappaEnhancement()*log(dipoles[i].s()/sqr(m0));
      return kw;
 }
 
 pair<double,double> Ropewalk::getMN(){
   pair<double,double> ret = make_pair<double,double>(0,0);
   for (int i = 0, N = dipoles.size(); i < N; ++i){
     ret.first += dipoles[i].m;
     ret.second += dipoles[i].n;
   }
   return ret;
 }
 
 double Ropewalk::lambdaSum(double cutoff){
   double ret = 0;
   for (int i = 0, N = dipoles.size(); i < N; ++i)
     ret += dipoles[i].s() > cutoff*GeV2 ? log(dipoles[i].s()/sqr(m0)) : 0;
   return ret;
 }
 
 
 double Ropewalk::Dipole::breakupProbability() const {
   if ( !breakable() || n + m <= 0.0 || n + m + 1 == p + q ) return 0.0;
   double sum = 0.0;
   for (int j = 0, N = overlaps.size(); j < N; ++j )
     if ( overlaps[j].dipole->breakable() )
       sum += abs(overlaps[j].yfrac);
   if ( sum <= 0.0 ) return 1.0;
   return double(n + m + 1 - p - q)/(sum + 1.0);
 }
 
 Step & Ropewalk::step() const {
   return *(CurrentGenerator()->currentStepHandler()->newStep());
 }
 
 Step & Ropewalk::Dipole::step() const {
   return *(CurrentGenerator()->currentStepHandler()->newStep());
 }
 // Helper class to describe a pair of excitations
 struct Exc {
 	// The constructor
 	Exc(double yIn, Energy gmassIn, PPtr p1In, PPtr p2In, Ropewalk::Dipole* dip1In, Ropewalk::Dipole* dip2In) : y(yIn), gluonMass(gmassIn), pp1(p1In), pp2(p2In), dip1(dip1In), dip2(dip2In) {
 		// Set a sensible starting vertex	
 		pp1->setVertex(dip1->pointAtRap(y));
 		pp2->setVertex(dip2->pointAtRap(y));
 		// Set a pointer to the excitation in the dipole
 		dip1->addExcitation(y, pp1);
 		dip2->addExcitation(y, pp2);
 	}
 
 	// Give the excitation a kick in the x and y direction,
 	void shove(Energy dpx, Energy dpy, HistKeeper* hkPtr){
 		// The old momenta
 		LorentzMomentum p2 = pp2->momentum();
 		LorentzMomentum p1 = pp1->momentum();
 		// The new momenta, after the shove
 		Energy mt2new = sqrt(sqr(p2.x() - dpx)  + sqr(p2.y() - dpy) + sqr(gluonMass)); 
 		Energy e2new = mt2new*cosh(y);
 		Energy p2znew = mt2new*sinh(y);
 		LorentzMomentum p2new(p2.x() - dpx, p2.y() - dpy, p2znew, e2new);
 
 		Energy mt1new = sqrt(sqr(p1.x() + dpx)  + sqr(p1.y() + dpy) + sqr(gluonMass)); 
 		Energy e1new = mt1new*cosh(y);
 		Energy p1znew = mt1new*sinh(y);
 		LorentzMomentum p1new(p1.x() + dpx, p1.y() + dpy, p1znew, e1new);
 
 		// The differences between the two
 		LorentzMomentum deltap1 = p1new - p1;
 		LorentzMomentum deltap2 = p2new - p2;
 		// We now want to check if we can add these
 		// two excitations to the dipoles
 		if( dip2->recoil(deltap2) ) {
 		  if ( dip1->recoil(deltap1) ) {
 		    pp1->setMomentum(p1new);
 		    pp2->setMomentum(p2new);
 		    if(hkPtr){
 		      LorentzMomentum ex2Rot = (dip2->R)*deltap2;
 		      LorentzMomentum ex1Rot = (dip1->R)*deltap1;
 		      hkPtr->hist("shoveInRestFrame")->fill(ex2Rot.perp()/GeV,hkPtr->currentWeight());
 		      hkPtr->hist("shoveInRestFrame")->fill(ex1Rot.perp()/GeV,hkPtr->currentWeight());
 			
 		    }
 		  } else {
 		    dip2->recoil(-deltap2);
 		    if(hkPtr){
 			LorentzMomentum ex2Rot = (dip2->R)*deltap2;
 			LorentzMomentum ex1Rot = (dip1->R)*deltap1;
 			hkPtr->hist("rejectedShoveInRestFrame")->fill(ex2Rot.perp()/GeV,hkPtr->currentWeight());
 			hkPtr->hist("rejectedShoveInRestFrame")->fill(ex1Rot.perp()/GeV,hkPtr->currentWeight());
 		    }
 		    
 		  }
 		}
 		else if(hkPtr){
 			LorentzMomentum ex2Rot = (dip2->R)*deltap2;
 			LorentzMomentum ex1Rot = (dip1->R)*deltap1;
 			hkPtr->hist("rejectedShoveInRestFrame")->fill(ex2Rot.perp()/GeV,hkPtr->currentWeight());
 			hkPtr->hist("rejectedShoveInRestFrame")->fill(ex1Rot.perp()/GeV,hkPtr->currentWeight());
 		}
 	}
 
 	LorentzPoint direction(){
 		// This gives the push direction
 		return (pp2->vertex()-pp1->vertex());
 	}
 
         
 	double y;
 	Energy gluonMass;	
 	PPtr pp1, pp2;	
 	Ropewalk::Dipole* dip1;
 	Ropewalk::Dipole* dip2;
 };
 
 
 
 void Ropewalk::shoveTheDipoles() {
   	typedef multimap<double, Ropewalk::Dipole *> RMap;
   	RMap rapDipoles;
 
  	// Order the dipoles in maxrapidity and insert new, excited dipole ends 
 	double ymin = 0;
 	double ymax = 0;
 	for(int i = 0, N = dipoles.size(); i < N ;++i){
 		if(dipoles[i].pc->decayed()){
 			// Set epc to the decay product of pc here
 			dipoles[i].epc = dipoles[i].pc->children()[0];
 		}
 		else{
 			// Make a new particle
 			dipoles[i].epc = CurrentGenerator()->getParticle(dipoles[i].pc->id());
 			dipoles[i].epc->setMomentum(dipoles[i].pc->momentum());
 			dipoles[i].epc->setVertex(dipoles[i].pc->vertex());
 			
 
 			step().addDecayProduct(dipoles[i].pc,dipoles[i].epc, false);
 		}
 		if(dipoles[i].pa->decayed()){
 			// Set epa to the decay product of pa here
 			dipoles[i].epa = dipoles[i].pa->children()[0];
 		}
 		else{
 			dipoles[i].epa = CurrentGenerator()->getParticle(dipoles[i].pa->id());
 			dipoles[i].epa->setMomentum(dipoles[i].pa->momentum());
 			dipoles[i].epa->setVertex(dipoles[i].pa->vertex());
 			step().addDecayProduct(dipoles[i].pa,dipoles[i].epa, false);
 		}
 		// order the dipoles in max rapidity
   		rapDipoles.insert(make_pair(dipoles[i].maxRapidity(), &dipoles[i]));
   		// find maximal and minimal rapidity to sample
 		if(dipoles[i].minRapidity() < ymin)
 			ymin = dipoles[i].minRapidity();
 		if(dipoles[i].maxRapidity() > ymax)
 			ymax = dipoles[i].maxRapidity();
 		
 	}
 
   	vector<double> rapidities;
 
 //	cout << rCutOff/femtometer << " " << gAmplitude/GeV << " " << gExponent << " " << yCutOff << " " << deltay << " " << tshove/femtometer << " " << deltat/femtometer << endl;
 
   	// We can let the gluon go off-shell between the pushes,
   	// and on-shell again towards the end
 	// Not fully implemented yet! Do not toggle this on!
   	bool gluonMass = false;
   
   
   	// Maybe do better sampling
   	for(double y = ymin; y < ymax; y+=deltay)
 		  rapidities.push_back(y);
 
 	  // For each value of ySample, we should have
 	  // an excitation pair per dipole we want to treat
 	  typedef map<double, vector<Exc> > ExMap;
 	  ExMap exPairs;
 	  Energy gMass = 0.001*keV;
 	  for(int i = 0, N = rapidities.size(); i < N; ++i){
 		  // find dipoles that are sampled here
 		  // and store them temporarily
 		  double ySample = rapidities[i];
 		  vector<Ropewalk::Dipole*> tmp;
 		  for(RMap::iterator rItr = rapDipoles.lower_bound(ySample);
 				  rItr != rapDipoles.end(); ++rItr){
 			  if(rItr->second->minRapidity() < ySample)
 			  	tmp.push_back(rItr->second);
 		  }
 		  // Construct the excitation particles, one for each sampled dipole
 		  vector<PPtr> eParticles;
 		  // dipoles to erase
 		  vector<int> eraseDipoles;
 		  for(int j = 0, M = tmp.size(); j < M; ++j){
 			  // Test if it is possible to add the small excitation to 
 			  // the dipole
 			  Energy pz = gMass*sinh(ySample);
 			  Energy e = gMass*cosh(ySample);
 			  LorentzMomentum ex = LorentzMomentum(0.0*GeV,
 					  0.0*GeV,pz,e);
 			  if(tmp[j]->recoil(ex,true)){
 			  	// Add the excitation
 				tmp[j]->recoil(ex);
 				eParticles.push_back(CurrentGenerator()->getParticle(21));
 			  	eParticles.back()->setMomentum(ex);
 				}
 		  	   else{
 			   	// if it was not possible, remove the dipole from the list
 				// but NOT inside the loop
 			   	eraseDipoles.push_back(j);
 			   }
 			}
 		    // Erase dipoles which could not bear an excitation
 		    for(int j = 0, M = eraseDipoles.size(); j < M; ++j){
 	    		    tmp.erase(tmp.begin() + (eraseDipoles[j]-j) );
 		    }
 	  
 		  // Construct all pairs of possible excitations in this slice
 		  exPairs[ySample] = vector<Exc>();
 		  for(int j = 0, M = tmp.size(); j < M; ++j)
 			  for(int k = j + 1; k < M; ++k){
 			  //	 Both dipoles should span the full rapidity interval
 				//if(tmp[j]->maxRapidity() >= ySample+deltay/2.0 && tmp[k]->maxRapidity() >= ySample+deltay/2.0
 				//		&& tmp[j]->minRapidity() <= ySample-deltay/2.0 
 				//			&& tmp[k]->minRapidity() <= ySample-deltay/2.0){
 					exPairs[ySample].push_back(Exc(ySample,gMass,eParticles[j],eParticles[k],tmp[j],tmp[k]));
 				//}
 			      }
   		}
  	 // For all times
 	 int ii = 0;
 	 
  	 for(Length t = 0*femtometer; t < tshove; t+=deltat){
 		 ++ii;
 		  // For all slices
 		  for(ExMap::iterator slItr = exPairs.begin(); slItr != exPairs.end(); ++slItr)
 			// For all excitation pairs
 			for(int i = 0, N = slItr->second.size(); i < N; ++i){
 				Exc& ep = slItr->second[i];
 				LorentzPoint direction = ep.direction();
 				Length dist = direction.perp();
 				if(hkPtr && ii < 6){
 					Histogram* hd = hkPtr->hist("dist"+to_string(ii));
 					hd->fill(dist/femtometer,hkPtr->currentWeight());
 				}
 				if(dist < rCutOff){
 					double gamma = 1.0;
 					if(lorentz){
 						LorentzMomentum pp = ep.dip1->momentum() + ep.dip2->momentum();
 						LorentzMomentum p1 = (ep.dip1->R)*pp;
 						LorentzMomentum p2 = (ep.dip2->R)*pp;
 						double gamma1 = sqrt(1 - sqr(p1.perp()/p1.e()));
 						double gamma2 = sqrt(1 - sqr(p2.perp()/p2.e()));
 						gamma = min(gamma1,gamma2);
 					}	
 					Energy gain = 0*GeV;
 					if(cylinderShove){
+						Length R = R0*gExponent;
+						gain = gamma*deltay*deltat*t*gAmplitude*dist/R/R*exp(-dist*dist/2/R/R);
 						/*if(dist > R0*gExponent){
 							Length R = R0*gExponent;
 							Area area = 2*R*R*acos(dist/2/R) - 0.5*dist*sqrt(4*R*R - dist*dist);
 							Energy inner = gAmplitude*area/M_PI/R/R;
 							gain = gamma*(sqrt((1*GeV + inner)*(1*GeV + inner)) - 1*GeV);
 						
 						}
 						else{
 							continue;
 						}
 						*/
 					}
 					else{
 						gain = gamma*deltay*(t+deltat)*deltat*gAmplitude/R0/gExponent/sqrt(2*M_PI)*
 							exp(-dist*dist/2/gExponent/gExponent/R0/R0);
 					}
 					Energy dpx = dist > ZERO ? gain*direction.x()/dist: 0.0*GeV;
 					Energy dpy = dist > ZERO ? gain*direction.y()/dist: 0.0*GeV;
 					
 					// Print stuff
 					if(hkPtr && ii < 6){
 						Histogram* h = hkPtr->hist("shove"+to_string(ii));
 						h->fill(gain/MeV,hkPtr->currentWeight());
 					}
 					ep.shove(dpx,dpy,hkPtr);
 				}
 			}
 	  	
 		// Propagate the dipoles
 		for(int i = 0, Nd = dipoles.size(); i < Nd; ++i)
 			dipoles[i].propagate(deltat, deltay);
 		}	
  
 	 // Now add the excitations to the dipoles
  	 for(int i = 0, Nd = dipoles.size(); i < Nd; ++i){
 			if(dipoles[i].excitations.size() > 0)
 				dipoles[i].excitationsToString(gluonMass, yCutOff, hkPtr);
 	 		else{
 				dipoles[i].epc->antiColourConnect(dipoles[i].epa);
 			}
 	 }
 	}
 
 multimap< double, pair<double, double> > Ropewalk::Dipole::getDistPairs(){
 	// Fill a container with the particle pair rapidities in lab system, 
 	// ordered by their spans
 	multimap< double, pair<double, double> > distPairs; 
 	DipEx::iterator iplusone = excitations.begin();
 	++iplusone;
 	for(DipEx::iterator itr = excitations.begin(); itr != excitations.end(); ++itr,++iplusone){
 		if(itr == excitations.begin()){
 			// First -- special
 			LorentzMomentum p1 = (pa->momentum().rapidity() == minRapidity() ? 
 				pa->momentum() : pc->momentum());
 			Energy2 s = (p1 + itr->second->momentum()).m2();
 			double ysep = (s > sqr(m0) ? 0.5*log(s/sqr(m0)) : 0.0);
 			distPairs.insert(make_pair(ysep, make_pair(minRapidity(),itr->first)) );
 		}
 		if(iplusone == excitations.end()){
 			// Last -- special
 			LorentzMomentum p1 = (pa->momentum().rapidity() == maxRapidity() ? 
 				pa->momentum() : pc->momentum());
 			Energy2 s = (p1 + itr->second->momentum()).m2();
 			double ysep = (s > sqr(m0) ? 0.5*log(s/sqr(m0)) : 0.0);
 			distPairs.insert(make_pair(ysep, make_pair(itr->first,maxRapidity())) );
 		}
 		else{
 			Energy2 s = (itr->second->momentum() + iplusone->second->momentum()).m2();
 			double ysep = (s > sqr(m0) ? 0.5*log(s/sqr(m0)) : 0.0);
 			distPairs.insert(make_pair(ysep, make_pair(itr->first,iplusone->first)));
 		}
 	}
 	return distPairs;
 	}
 
 
 void Ropewalk::Dipole::excitationsToString(bool gluonMass, double yCutOff, HistKeeper* hkPtr){
 	if(gluonMass){
 		cout << "Oops! Not implemented yet!" << endl;
 		return;
 	}
 	// Clustering should always be turned on
 	// only turn it off for debugging purposes.
 	// Change the parameters DeltaY or YCutOff instead
 	bool clustering = true;
 	if(clustering){
 		// Clustering
 		// 
 		// For all excitation neighbors in the lab-system, 
 		// we calculate their effective rapidity span
 		// and keep only those above yCutOff
 	
 		multimap<double, pair<double, double> > distPairs = getDistPairs();
 
 		if(hkPtr){
 			for(auto itr = distPairs.begin(); itr != distPairs.end(); ++itr)
 				hkPtr->hist("yDistBefore")->fill(itr->first,hkPtr->currentWeight());
 	
 		}	
 
 		if(distPairs.begin() != distPairs.end())
 		while(distPairs.begin()->first < yCutOff){
 			// There is only one excitation on the string
 			// The ends will share the momentum provided 
 			// that both distances are small
 			multimap<double, pair<double, double> >::iterator itr = distPairs.begin();
 			if(distPairs.size() == 2 && distPairs.rbegin()->first < yCutOff){
 				DipEx::iterator exP = excitations.find(itr->second.second);
 				if(exP == excitations.end())
 					exP = excitations.find(itr->second.first);
 				LorentzMomentum panew = epa->momentum() +
 				       	0.5*exP->second->momentum();
 				LorentzMomentum pcnew = epc->momentum() +
 				       	0.5*exP->second->momentum();
 					epa->setMomentum(panew);
 					epc->setMomentum(pcnew);
 					excitations.erase(exP);
 			}
 			// If it is the first piece, put the momentum on the dipole end
 			else if(itr->second.first == minRapidity()){
 				LorentzMomentum pnew = (epa->momentum().rapidity() == minRapidity() ? 
 					epa->momentum() : epc->momentum());
 				pnew+=excitations[itr->second.second]->momentum();
 				if(epa->momentum().rapidity() == minRapidity())
 					epa->setMomentum(pnew);
 				else
 					epc->setMomentum(pnew);
 				// Erase the excitation
 				excitations.erase(itr->second.second);
 			}
 			// If it is the last piece ditto...
 			else if(itr->second.second == maxRapidity()){
 				LorentzMomentum pnew = (epa->momentum().rapidity() == maxRapidity() ? 
 					epa->momentum() : epc->momentum());
 				pnew+=excitations[itr->second.first]->momentum();
 				if(epa->momentum().rapidity() == maxRapidity())
 					epa->setMomentum(pnew);
 				else
 					epc->setMomentum(pnew);
 				// Erase the excitation
 				excitations.erase(itr->second.first);
 			}
 			else{
 				LorentzMomentum pnew = excitations[itr->second.first]->momentum() +
 						excitations[itr->second.second]->momentum();
 				// update the first
 				excitations[itr->second.first]->setMomentum(pnew);
 				// erase the second
 				excitations.erase(itr->second.second);
 			}
 			// We can surely do better than recalculating everything
 			// each time - lets see if it kills us
 			
 			if(excitations.empty())
 				break;
 			distPairs = getDistPairs();
 		}
 		if(hkPtr){
 			hkPtr->hist("nExcitations")->fill(excitations.size(),hkPtr->currentWeight());
 			for(auto itr = distPairs.begin(); itr != distPairs.end(); ++itr)
 				hkPtr->hist("yDistAfter")->fill(itr->first,hkPtr->currentWeight());
 
 		}
 		//
 		
 	}	
 	// Go through the remaining excitations and sanity check them
 	for(DipEx::iterator itr = excitations.begin(); itr != excitations.end(); ++itr){
 		// In the dipole rest frame, we should have pz == 0
 		//LorentzMomentum ppmom = R*itr->second->momentum();
 		//LorentzMomentum ppn(ppmom.x(),ppmom.y(),0*GeV,ppmom.t());
 		//itr->second->setMomentum(R.inverse()*ppn);
 		
 		LorentzMomentum ppm = itr->second->momentum();
 		if(fabs(ppm.x()/GeV) < 1e-5 && fabs(ppm.y()/GeV) < 1e-5 && fabs(ppm.z()/GeV) < 1e-5 )
 			excitations.erase(itr);
 		else if(hkPtr){
 			hkPtr->hist("excitationPt")->fill(ppm.perp()/GeV,hkPtr->currentWeight());
 			LorentzMomentum ppr = R*ppm;
 			hkPtr->hist("excitationRestFramePt")->fill(ppr.perp()/GeV,hkPtr->currentWeight());
 		}
 	
 	}
 	
 	// If we dont have any excitations, we are done	
 	if(excitations.empty()){
 		epa->colourConnect(epc);
 		return;
 		
 	}
 	
 	// Flag if we start from the colored parton
 	bool color = false;
 	// Link the first excitation to the dipole end with the smallest rapidity
 	if(minRapidity() == epc->momentum().rapidity()){
 		epa->colourConnect(excitations.rbegin()->second);
 		epc->antiColourConnect(excitations.begin()->second);
 		//excitations.begin()->second->colourConnect(epc);
 		//excitations.rbegin()->second->antiColourConnect(epa);
 		step().addDecayProduct(pc,excitations.begin()->second,false);
 		color = true;
 	}
 	else{
 		epa->colourConnect(excitations.begin()->second);
 		epc->antiColourConnect(excitations.rbegin()->second);
 		//excitations.begin()->second->antiColourConnect(epa);
 		//excitations.rbegin()->second->colourConnect(epc);
 		step().addDecayProduct(pa,excitations.begin()->second,false);
 	}
 	// If we have only one excitation, we are quickly done
 	if(excitations.size() == 1)
 		return;
 
 	// We have more...
 	DipEx::iterator iplusone = excitations.begin();
 	++iplusone;	
 	for(DipEx::iterator itr = excitations.begin(); iplusone != excitations.end(); ++itr,++iplusone){
 		// Are we halfway through?
 		bool halfway = double(distance(excitations.begin(),iplusone))/double(excitations.size()) > 0.5;
 		if(color){
 			itr->second->antiColourConnect(iplusone->second);
 			//iplusone->second->colourConnect(itr->second);
 			step().addDecayProduct((halfway ? pa : pc), iplusone->second,false);
 		}	
 		else{
 			itr->second->colourConnect(iplusone->second);
 			//iplusone->second->antiColourConnect(itr->second);
 			step().addDecayProduct((halfway ? pc : pa), iplusone->second,false);
 		}	
 	}
 	
 	}
 
 void Ropewalk::Dipole::propagate(Length deltat, double deltay){
     	const Lorentz5Momentum& pcm = epc->momentum();
 	const Lorentz5Momentum& pam = epa->momentum();
 
 	if(pcm.e()/GeV == 0 || pam.e()/GeV == 0)
 		Throw<ColourException>()
 		<< "Tried to propagate a dipole end with energy 0; this should never happen."
 		<< "This is a serious error - please contact the authors."
 		<< Exception::abortnow;
 	// Propagate in dipole rest frame
 	bc = R*(bc + deltat * pcm/(pcm.e())); 
 	ba = R*(ba + deltat * pam/(pam.e()));
 
 	// Propagate in the lab frame
 	LorentzPoint bclab = epc->vertex() + deltat*pcm/pcm.e();
 	LorentzPoint balab = epa->vertex() + deltat*pam/pam.e();
 	
 	epc->setVertex(bclab);
 	epa->setVertex(balab);
 	//const_cast<ThePEG::Particle& >((*pc)).setVertex(bclab);
 	//const_cast<ThePEG::Particle& >((*pa)).setVertex(balab);
 
 	for(DipEx::iterator eItr = excitations.begin(); eItr != excitations.end(); ++eItr){
     		const Lorentz5Momentum& em = eItr->second->momentum();
 	        // Propagate excitations only in lab frame
 		// only if it has been pushed
 		if(em.e()/GeV > 0){
 			eItr->second->setVertex(eItr->second->vertex() + deltat*em/(em.perp() + m0*deltay*deltay));	
 		}	
 		else{
 			eItr->second->setVertex(pointAtRap(eItr->first));
 		}
 	}
 }	
 
 void Ropewalk::doBreakups() {
 
   typedef multimap<double, const Dipole *> BMap;
   BMap breakups;
 
   // First order alldipoles in increasing probability of breaking
   for ( int i = 0, N = dipoles.size(); i < N; ++i )
     breakups.insert(make_pair(dipoles[i].breakupProbability(), &dipoles[i]));
 
   // Then start breaking in reverse order
   mspec.clear();
   for ( BMap::reverse_iterator it = breakups.rbegin();
 	it != breakups.rend(); ++it ) {
     const Dipole & d = *it->second;
     if ( d.breakupProbability() < UseRandom::rnd() ) continue;
     mspec.push_back(d.s()/GeV2);
     double hinv = 1.0 / d.kappaEnhancement();  
     // The default parameters should be set                                                                                                                                        
     // properly from the outside. Now just Pythia8 defaults                                                                                                                        
     double rho = pow(0.215, hinv);
     double x = pow(1.0,hinv);
     double y = pow(0.027,hinv);
 
     Selector<int> qsel;
     qsel.clear();
     if(UseRandom::rnd() < junctionDiquarkProb){  
     // Take just ordinary quarks
       qsel.insert(1.0, ParticleID::ubar);
       qsel.insert(1.0, ParticleID::dbar);
       qsel.insert(rho, ParticleID::sbar);
     }
     else {
       // Take diquarks
       // TODO (Pythia 8.2) Set status code of these diquarks to 74
       qsel.insert(1.0, ParticleID::ud_0);
       qsel.insert(3.0*y, ParticleID::dd_1);
       qsel.insert(3.0*y, ParticleID::ud_1);
       qsel.insert(3.0*y, ParticleID::uu_1);
       qsel.insert(rho*x, ParticleID::su_0);
       qsel.insert(3*x*rho*y, ParticleID::su_1);
       qsel.insert(3*y*x*x*rho*rho, ParticleID::ss_1);
       qsel.insert(rho*x, ParticleID::sd_0);
       qsel.insert(3*x*rho*y, ParticleID::sd_1);
     }
     int flav = qsel[UseRandom::rnd()];
     PPtr dic = CurrentGenerator()->getParticle(flav);
     PPtr dia = CurrentGenerator()->getParticle(-flav);
     //cout << (dic->momentum() + dia->momentum()).m2() / GeV2 << " " <<  d.s() / GeV2 << endl;
     if((dic->momentum() + dia->momentum()).m2() > d.s()) continue;
     // Get boost to dipole rest frame and place the di-quarks there.
     LorentzRotation R = Utilities::getBoostFromCM(make_pair(d.pc, d.pa));
 
     SimplePhaseSpace::CMS(dic, dia, d.s(), 1.0, 0.0);
     dia->transform(R);
     dic->transform(R);
     // Add the di-quarks as children to the decayed gluons and split
     // the resulting string.
     if ( !( step().addDecayProduct(d.pc, dic, true) &&
 	    step().addDecayProduct(d.pa, dia, true) && 
 	    step().addDecayProduct(d.pc, dia, false) &&
 	    step().addDecayProduct(d.pa, dic, false)) )
       Throw<ColourException>()
 	<< "Adding decay products failed in Ropewalk. "
 	<< "This is a serious error - please contact the authors."
 	<< Exception::abortnow;
     tcParticleSet pset(d.string->partons().begin(), d.string->partons().end());
     pset.erase(d.pc);
     pset.erase(d.pa);
     pset.insert(dic);
     pset.insert(dia);
     // Reset the neighboring dipoles to point to the new diquarks.
     d.broken = true;
     ColourSinglet * olds = d.string;
     const vector<Dipole *> & oldd = stringdipoles[olds];
     for ( int id = 0, Nd = oldd.size(); id < Nd; ++id ) {
       if ( oldd[id]->pc == d.pa ) oldd[id]->pc = dia;
       if ( oldd[id]->pa == d.pc ) oldd[id]->pa = dic;
     }
     // remove the old string and insert the new ones fixing the
     // pointers from the dipoles.
     vector<ColourSinglet> newstrings =
       ColourSinglet::getSinglets(pset.begin(), pset.end());
     for ( int is = 0, Ns = newstrings.size(); is < Ns; ++is ) {
       ColourSinglet * news = new ColourSinglet(newstrings[is]);
       tcParticleSet pset(news->partons().begin(), news->partons().end());
       vector<Dipole *> & newd = stringdipoles[news];
       for ( int id = 0, Nd = oldd.size(); id < Nd; ++id ) {
 	if ( !oldd[id]->broken && pset.find(oldd[id]->pc) != pset.end() ) {
 	  newd.push_back(oldd[id]);
 	  oldd[id]->string = news;
 	}
       }
       sort(newd, news->partons()[0]);
     }
     stringdipoles.erase(olds);
     delete olds;
   }
 }
 
 vector< pair<ColourSinglet,double> > Ropewalk::getSinglets(double DeltaY) const {
   vector< pair<ColourSinglet,double> > ret;
   ret.reserve(stringdipoles.size());
   double toty = 0.0;
   double totyh = 0.0;
   double toth = 0.0;
   double toth2 = 0.0;
   double minh = 10.0;
   double maxh = 0.0;
   // Calculate the kappa-enhancement of the remaining strings.
   for ( DipoleMap::const_iterator it = stringdipoles.begin();
 	it != stringdipoles.end(); ++it ) {
     
     double sumyh = 0.0;
     double sumy = 0.0;
     for ( int id = 0, Nd = it->second.size(); id < Nd; ++id ) {
       double y = it->second[id]->yspan(m0);
       double h = it->second[id]->kappaEnhancement();
       avh += h*it->second[id]->yspan(1.0*GeV);
       strl += it->second[id]->yspan(1.0*GeV);
       if ( DeltaY > 0.0 &&
 	   abs(it->second[id]->pc->eta()) > DeltaY &&
 	   abs(it->second[id]->pa->eta()) > DeltaY ) continue;
       sumy += y;
       sumyh += y*h;
     }
     toty += sumy;
     totyh += sumyh;
     
     if ( sumy > 0.0 ) {
       double h = 0.1*int(10.0*sumyh/sumy + UseRandom::rnd());
       ret.push_back(make_pair(*it->first, h));
       toth += sumyh/sumy;
       toth2 += sqr(sumyh/sumy);
       minh = min(minh, sumyh/sumy);
       maxh = max(maxh, sumyh/sumy);
     } else {
       ret.push_back(make_pair(*it->first, 1.0));
       toth += 1.0;
       toth2 += 1.0;
       minh = min(minh, 1.0);
       maxh = max(maxh, 1.0);
     }
   }
   if ( debug )
     CurrentGenerator::log() << ret.size() << "ns "
 			    << totyh/max(toty, 0.00001) << "hwa "
 			    << minh << "<h "
 			    << toth/ret.size() << "ha "
 			    << maxh << ">h "
 			    << sqrt(toth2/ret.size() - sqr(toth/ret.size())) << "hsd " << endl;
 
   if ( avh > 0.0 ) avh /= strl;
   if ( avp > 0.0 ) avp /= strl0;
   if ( avq > 0.0 ) avq /= strl0;
 
   return ret;
 
 }
 
 double Ropewalk::averageKappaEnhancement(const vector<Dipole *> & dipoles,
 					 double DeltaY) const {
     double sumyh = 0.0;
     double sumy = 0.0;
     for ( int id = 0, Nd = dipoles.size(); id < Nd; ++id ) {
       dipoles[id]->reinit(UseRandom::rnd(), R0, m0);
       double y = dipoles[id]->yspan(m0);
       double h = dipoles[id]->firstKappa();
       if ( DeltaY > 0.0 &&
 	   abs(dipoles[id]->pc->eta()) > DeltaY &&
 	   abs(dipoles[id]->pa->eta()) > DeltaY ) continue;
       sumy += y;
       sumyh += y*h;
     }
     if ( sumy <= 0.0 ) return 1.0;
     return sumyh/sumy;
 }
 
 void Ropewalk::sort(vector<Dipole *> & dips, tcPPtr p) {
   if ( p->antiColourLine() ) {
     map<tcPPtr, Dipole *> dmap;
     Dipole * current = 0;
     for ( int i = 0, N = dips.size(); i < N; ++i ) {
       if ( dips[i]->pa == p ) current =  dips[i];
       else dmap[dips[i]->pa] = dips[i];
     }
     dips.clear();
     while ( current ) {
       dips.push_back(current);
       map<tcPPtr, Dipole *>::iterator it = dmap.find(current->pc);
       if ( it == dmap.end() ) current = 0;
       else {
 	current = it->second;
 	dmap.erase(it);
       }
     }
     if ( !dmap.empty() )
       Throw<ColourException>()
 	<< "Failed to sort dipoles in Ropewalk. "
 	<< "This is a serious error - please contact the authors."
 	<< Exception::abortnow;
   } else {
     map<tcPPtr, Dipole *> dmap;
     Dipole * current = 0;
     for ( int i = 0, N = dips.size(); i < N; ++i ) {
       if ( dips[i]->pc == p ) current =  dips[i];
       else dmap[dips[i]->pc] = dips[i];
     }
     dips.clear();
     while ( current ) {
       dips.push_back(current);
       map<tcPPtr, Dipole *>::iterator it = dmap.find(current->pa);
       if ( it == dmap.end() ) current = 0;
       else {
 	current = it->second;
 	dmap.erase(it);
       }
     }
     if ( !dmap.empty() )
       Throw<ColourException>()
 	<< "Failed to sort dipoles in Ropewalk. "
 	<< "This is a serious error - please contact the authors."
 	<< Exception::abortnow;
   }
 }