diff --git a/current_generator/jW_j.frm b/current_generator/jW_j.frm
new file mode 100644
index 0000000..60d3930
--- /dev/null
+++ b/current_generator/jW_j.frm
@@ -0,0 +1,35 @@
+*/**
+*  \brief Contraction of W current with FKL current
+*
+*  \authors   The HEJ collaboration (see AUTHORS for details)
+*  \date      2020
+*  \copyright GPLv2 or later
+*/
+#include- include/helspin.frm
+#include- include/write.frm
+
+v pb,p2,pa,p1,pg,pl,plbar,pW;
+i mu,nu,sigma,alpha;
+cf jW,epsg,m2,sqrt;
+s h;
+
+#do h2={+,-}
+   l [jW_j `h2'] = jW(-1, pa, p1, plbar, pl)*Current(`h2'1, p2, mu, pb);
+#enddo
+
+* eq:Weffcur1 in developer manual
+id jW(h?, pa?, p1?, plbar?, pl?) = Current(-1, pl, alpha, plbar)*(
+   + Current(h,p1,alpha,p1+pW,mu,pa)/m2(p1+pW)
+   + Current(h,p1,mu,pa-pW,alpha,pa)/m2(pa-pW)
+);
+
+multiply replace_(pW,pl+plbar);
+.sort
+#call ContractCurrents
+.sort
+format O4;
+format c;
+#call WriteHeader(`OUTPUT')
+#call WriteOptimised(`OUTPUT',jW_j,1,pa,p1,pb,p2,pl,plbar)
+#call WriteFooter(`OUTPUT')
+.end
diff --git a/src/Wjets.cc b/src/Wjets.cc
index 06f0c9f..5ecc097 100644
--- a/src/Wjets.cc
+++ b/src/Wjets.cc
@@ -1,782 +1,736 @@
 /**
  *  \authors   The HEJ collaboration (see AUTHORS for details)
  *  \date      2019
  *  \copyright GPLv2 or later
  */
 #include "HEJ/Wjets.hh"
 
 #include <array>
 #include <iostream>
 
 #include "HEJ/Constants.hh"
 #include "HEJ/EWConstants.hh"
 #include "HEJ/jets.hh"
 #include "HEJ/Tensor.hh"
 #include "HEJ/LorentzVector.hh"
 #include "HEJ/exceptions.hh"
 
 // generated headers
+#include "HEJ/currents/jW_j.hh"
 #include "HEJ/currents/jWuno_j.hh"
 #include "HEJ/currents/jWqqbar_j.hh"
 #include "HEJ/currents/jW_qqbar_j.hh"
 #include "HEJ/currents/j_Wqqbar_j.hh"
 #include "HEJ/currents/jW_jqqbar.hh"
 #include "HEJ/currents/jW_juno.hh"
 
-using HEJ::Tensor;
-using HEJ::init_sigma_index;
-using HEJ::metric;
-using HEJ::rank3_current;
-using HEJ::rank5_current;
-using HEJ::eps;
-using HEJ::to_tensor;
 using HEJ::Helicity;
-using HEJ::angle;
-using HEJ::square;
-using HEJ::flip;
 using HEJ::ParticleProperties;
 
 namespace helicity = HEJ::helicity;
 
 namespace { // Helper Functions
   // FKL W Helper Functions
   double WProp (const HLV & plbar, const HLV & pl, ParticleProperties const & wprop){
     COM propW = COM(0.,-1.)/( (pl+plbar).m2() - wprop.mass*wprop.mass
                             + COM(0.,1.)*wprop.mass*wprop.width);
     double PropFactor=(propW*conj(propW)).real();
     return PropFactor;
   }
 
-  namespace {
-    // FKL current including W emission off negative helicities
-    // See eq. (87) {eq:jW-} in developer manual
-    // Note that the terms are rearranged
-    Tensor<1> jW_minus(
-        HLV const & pa, HLV const & p1,
-        HLV const & plbar, HLV const & pl
-    ){
-      using HEJ::helicity::minus;
-
-      const double tWin = (pa-pl-plbar).m2();
-      const double tWout = (p1+pl+plbar).m2();
-
-      // C++ arithmetic operators are evaluated left-to-right,
-      // so the following first computes complex scalar coefficients,
-      // which then multiply a current, reducing the number
-      // of multiplications
-      return 2.*(
-          + angle(p1, pl)*square(p1, plbar)/tWout
-          + square(pa, plbar)*angle(pa, pl)/tWin
-      )*HEJ::current(p1, pa, helicity::minus)
-        + 2.*angle(p1, pl)*square(pl, plbar)/tWout
-            *HEJ::current(pl, pa, helicity::minus)
-        + 2.*square(pa, plbar)*angle(pl, plbar)/tWin
-            *HEJ::current(p1, plbar, helicity::minus);
-    }
-  }
-
-  // FKL current including W emission
-  // see eqs. (87), (88) {eq:jW-}, {eq:jW+} in developer manual
-  Tensor<1> jW(
-      HLV const & pa, HLV const & p1,
-      HLV const & plbar, HLV const & pl,
-      Helicity h
-  ){
-    if(h == helicity::minus) {
-      return jW_minus(pa, p1, plbar, pl);
-    }
-    return jW_minus(pa, p1, pl, plbar).complex_conj();
-  }
-
   /**
    * @brief  Contraction of W + unordered jet current with FKL current
    *
    * See eq:wunocurrent in the developer manual for the definition
    * of the W + unordered jet current
    */
   template<Helicity h1, Helicity h2, Helicity pol>
   double jM2Wuno(
       HLV const & pg, HLV const & p1, HLV const & plbar, HLV const & pl,
       HLV const & pa, HLV const & p2, HLV const & pb,
       ParticleProperties const & wprop
   ){
     using HEJ::C_A;
     using HEJ::C_F;
 
     const COM U1 = HEJ::U1<h1, h2, pol>(p1, p2, pa, pb, pg, pl, plbar);
     const COM U2 = HEJ::U2<h1, h2, pol>(p1, p2, pa, pb, pg, pl, plbar);
     const COM L = HEJ::L<h1, h2, pol>(p1, p2, pa, pb, pg, pl, plbar);
 
     const COM X = U1 - L;
     const COM Y = U2 + L;
 
     double amp = C_A*C_F*C_F/2.*(norm(X)+norm(Y)) - HEJ::C_F/2.*(X*conj(Y)).real();
     amp *= WProp(plbar, pl, wprop);
 
     const HLV q1g = pa-pl-plbar-p1-pg;
     const HLV q2 = p2-pb;
 
     const double t1 = q1g.m2();
     const double t2 = q2.m2();
 
     amp /= (t1*t2);
     return amp;
   }
 
   /**
    * @brief Contraction of W + extremal qqbar current with FKL current
    *
    * See eq:crossed in the developer manual for the definition
    * of the W + extremal qqbar current.
    *
    */
   template<Helicity h1, Helicity h2, Helicity hg>
   double jM2_W_extremal_qqbar(
     HLV const & pg, HLV const & pq, HLV const & plbar, HLV const & pl,
     HLV const & pqbar, HLV const & p3, HLV const & pb,
     ParticleProperties const & wprop
   ){
     using HEJ::C_A;
     using HEJ::C_F;
 
     const COM U1Xcontr = HEJ::U1X<h1, h2, hg>(pg, pq, plbar, pl, pqbar, p3, pb);
     const COM U2Xcontr = HEJ::U2X<h1, h2, hg>(pg, pq, plbar, pl, pqbar, p3, pb);
     const COM LXcontr = HEJ::LX<h1, h2, hg>(pg, pq, plbar, pl, pqbar, p3, pb);
 
     const COM X = U1Xcontr - LXcontr;
     const COM Y = U2Xcontr + LXcontr;
 
     double amp = C_A*C_F*C_F/2.*(norm(X)+norm(Y)) - HEJ::C_F/2.*(X*conj(Y)).real();
     amp *= WProp(plbar, pl, wprop);
 
     // what do I have to put here?
     const HLV q1 = pg-pl-plbar-pq-pqbar;
     const HLV q2 = p3-pb;
 
     const double t1 = q1.m2();
     const double t2 = q2.m2();
 
     amp /= (t1*t2);
     return amp;
   }
 
 //! W+Jets FKL Contributions
 /**
  * @brief W+Jets FKL Contributions, function to handle all incoming types.
  * @param p1out             Outgoing Particle 1. (W emission)
  * @param plbar             Outgoing election momenta
  * @param pl                Outgoing neutrino momenta
  * @param p1in              Incoming Particle 1. (W emission)
  * @param p2out             Outgoing Particle 2
  * @param p2in              Incoming Particle 2
  * @param aqlineb           Bool. Is Backwards quark line an anti-quark line?
  * @param aqlinef           Bool. Is Forwards quark line an anti-quark line?
  *
  * Calculates j_W ^\mu    j_\mu.
  * Handles all possible incoming states.
  */
   double jW_j( HLV p1out, HLV plbar, HLV pl, HLV p1in, HLV p2out, HLV p2in,
                bool aqlineb, bool /* aqlinef */,
                ParticleProperties const & wprop
     ){
     using helicity::minus;
     using helicity::plus;
     const HLV q1=p1in-p1out-plbar-pl;
     const HLV q2=-(p2in-p2out);
 
     const double WPropfact = WProp(plbar, pl, wprop);
 
-    const auto j_W = COM{0,-1}*jW(p1in, p1out, plbar, pl, aqlineb?plus:minus);
-    double Msqr = 0.;
-    for(const auto h: {plus, minus}) {
-      const auto j = HEJ::current(p2out, p2in, h);
-      Msqr += abs2(j_W.contract(j, 1));
-    }
+    // we assume that the W is emitted off a quark line
+    // if this is not the case, we have to apply CP conjugation,
+    // which is equivalent to swapping lepton and antilepton momenta
+    if(aqlineb) std::swap(pl, plbar);
+
+    const COM ampm = HEJ::jW_j<minus>(p1in,p1out,p2in,p2out,pl,plbar);
+    const COM ampp = HEJ::jW_j<plus>(p1in,p1out,p2in,p2out,pl,plbar);
+
+    const double Msqr = std::norm(ampm) + std::norm(ampp);
+
     // Division by colour and Helicity average (Nc2-1)(4)
     // Multiply by Cf^2
     return HEJ::C_F*HEJ::C_F*WPropfact*Msqr/(q1.m2()*q2.m2()*(HEJ::N_C*HEJ::N_C - 1)*4);
   }
 } // Anonymous Namespace
 
 double ME_W_qQ (HLV p1out, HLV plbar, HLV pl,HLV p1in, HLV p2out, HLV p2in,
    ParticleProperties const & wprop
 ){
   return jW_j(p1out, plbar, pl, p1in, p2out, p2in, false, false, wprop);
 }
 
 double ME_W_qQbar (HLV p1out, HLV plbar, HLV pl,HLV p1in, HLV p2out, HLV p2in,
    ParticleProperties const & wprop
 ){
   return jW_j(p1out, plbar, pl, p1in, p2out, p2in, false, true, wprop);
 }
 
 double ME_W_qbarQ (HLV p1out, HLV plbar, HLV pl,HLV p1in, HLV p2out, HLV p2in,
    ParticleProperties const & wprop
 ){
   return jW_j(p1out, plbar, pl, p1in, p2out, p2in, true, false, wprop);
 }
 
 double ME_W_qbarQbar (HLV p1out, HLV plbar, HLV pl,HLV p1in, HLV p2out, HLV p2in,
    ParticleProperties const & wprop
 ){
   return jW_j(p1out, plbar, pl, p1in, p2out, p2in, true, true, wprop);
 }
 
 double ME_W_qg (HLV p1out, HLV plbar, HLV pl,HLV p1in, HLV p2out, HLV p2in,
    ParticleProperties const & wprop
 ){
   return jW_j(p1out, plbar, pl, p1in, p2out, p2in, false, false, wprop)
           *K_g(p2out, p2in)/HEJ::C_F;
 }
 
 double ME_W_qbarg (HLV p1out, HLV plbar, HLV pl,HLV p1in, HLV p2out, HLV p2in,
    ParticleProperties const & wprop
 ){
   return jW_j(p1out, plbar, pl, p1in, p2out, p2in, true, false, wprop)
           *K_g(p2out, p2in)/HEJ::C_F;
 }
 
 namespace{
   // helicity amplitude squares for contraction of W current with unordered current
   template<Helicity h2, Helicity hg>
   double ampsq_jW_juno(
     HLV const & pa, HLV const & p1,
     HLV const & pb, HLV const & p2,
     HLV const & pg,
     HLV const & pl, HLV const & plbar
   ){
     const COM U1 = HEJ::U1_jW<h2,hg>(pa,p1,pb,p2,pg,pl,plbar);
     const COM U2 = HEJ::U2_jW<h2,hg>(pa,p1,pb,p2,pg,pl,plbar);
     const COM L = HEJ::L_jW<h2,hg>(pa,p1,pb,p2,pg,pl,plbar);
 
     return 2.*HEJ::C_F*std::real((L-U1)*std::conj(L+U2))
       + 2.*HEJ::C_F*HEJ::C_F/3.*std::norm(U1+U2)
       ;
   }
 
   /**
    * @brief W+Jets Unordered Contributions, function to handle all incoming types.
    * @param p1out             Outgoing Particle 1. (W emission)
    * @param plbar             Outgoing election momenta
    * @param pl                Outgoing neutrino momenta
    * @param p1in              Incoming Particle 1. (W emission)
    * @param p2out             Outgoing Particle 2 (Quark, unordered emission this side.)
    * @param p2in              Incoming Particle 2 (Quark, unordered emission this side.)
    * @param pg                Unordered Gluon momenta
    * @param aqlineb           Bool. Is Backwards quark line an anti-quark line?
    * @param aqlinef           Bool. Is Forwards quark line an anti-quark line?
    *
    * Calculates j_W ^\mu    j_{uno}_\mu. Ie, unordered with W emission opposite side.
    * Handles all possible incoming states.
    */
   double jW_juno(
     HLV p1out, HLV plbar, HLV pl,HLV p1in, HLV p2out,
     HLV p2in, HLV pg, bool aqlineb, bool /* aqlinef */,
     ParticleProperties const & wprop
   ){
     using helicity::minus;
     using helicity::plus;
 
     // we assume that the W is emitted off a quark line
     // if this is not the case, we have to apply CP conjugation,
     // which is equivalent to swapping lepton and antilepton momenta
     if(aqlineb) std::swap(pl, plbar);
 
     // helicity assignments assume aqlinef == false
     // in the end, this is irrelevant since we sum over all helicities
     const double ampsq =
       + ampsq_jW_juno<minus, minus>(p1in,p1out,p2in,p2out,pg,pl,plbar)
       + ampsq_jW_juno<minus, plus>(p1in,p1out,p2in,p2out,pg,pl,plbar)
       + ampsq_jW_juno<plus, minus>(p1in,p1out,p2in,p2out,pg,pl,plbar)
       + ampsq_jW_juno<plus, plus>(p1in,p1out,p2in,p2out,pg,pl,plbar)
       ;
 
     const HLV q1=p1in-p1out-plbar-pl;
     const HLV q2=-(p2in-p2out-pg);
 
     return WProp(plbar, pl, wprop)*ampsq/((16)*(q2.m2()*q1.m2()));
   }
 }
 double ME_W_unob_qQ(HLV p1out, HLV p1in, HLV p2out, HLV p2in,
                     HLV pg, HLV plbar, HLV pl,
                     ParticleProperties const & wprop
 ){
   return jW_juno(p2out, plbar, pl, p2in, p1out, p1in, pg, false, false, wprop);
 }
 
 double ME_W_unob_qQbar(HLV p1out, HLV p1in, HLV p2out, HLV p2in,
                        HLV pg, HLV plbar, HLV pl,
                        ParticleProperties const & wprop
 ){
   return jW_juno(p2out, plbar, pl, p2in, p1out, p1in, pg, false, true, wprop);
 }
 
 double ME_W_unob_qbarQ(HLV p1out, HLV p1in, HLV p2out, HLV p2in,
                        HLV pg, HLV plbar, HLV pl,
                        ParticleProperties const & wprop
 ){
   return jW_juno(p2out, plbar, pl, p2in, p1out, p1in, pg, true, false, wprop);
 }
 
 double ME_W_unob_qbarQbar(HLV p1out, HLV p1in, HLV p2out, HLV p2in,
                           HLV pg, HLV plbar, HLV pl,
                           ParticleProperties const & wprop
 ){
   return jW_juno(p2out, plbar, pl, p2in, p1out, p1in, pg, true, true, wprop);
 }
 
 namespace{
 
   // helicity sum helper for jWuno_j(...)
   template<Helicity h1>
     double jWuno_j_helsum(
       HLV const & pg, HLV const & p1, HLV const & plbar, HLV const & pl,
       HLV const & pa, HLV const & p2, HLV const & pb,
       ParticleProperties const & wprop
     ){
     using helicity::minus;
     using helicity::plus;
 
     const double ME2h1pp = jM2Wuno<h1, plus, plus>(
       pg, p1, plbar, pl, pa, p2, pb, wprop
     );
 
     const double ME2h1pm = jM2Wuno<h1, plus, minus>(
       pg, p1, plbar, pl, pa, p2, pb, wprop
     );
 
     const double ME2h1mp = jM2Wuno<h1, minus, plus>(
       pg, p1, plbar, pl, pa, p2, pb, wprop
     );
 
     const double ME2h1mm = jM2Wuno<h1, minus, minus>(
       pg, p1, plbar, pl, pa, p2, pb, wprop
     );
 
     return ME2h1pp + ME2h1pm + ME2h1mp + ME2h1mm;
   }
 
 /**
  * @brief W+Jets Unordered Contributions, function to handle all incoming types.
  * @param pg                Unordered Gluon momenta
  * @param p1out             Outgoing Particle 1. (Quark - W and Uno emission)
  * @param plbar             Outgoing election momenta
  * @param pl                Outgoing neutrino momenta
  * @param p1in              Incoming Particle 1. (Quark - W and Uno emission)
  * @param p2out             Outgoing Particle 2
  * @param p2in              Incoming Particle 2
  * @param aqlineb           Bool. Is Backwards quark line an anti-quark line?
  *
  * Calculates j_W_{uno} ^\mu    j_\mu. Ie, unordered with W emission same side.
  * Handles all possible incoming states. Note this handles both forward and back-
  * -ward Wuno emission. For forward, ensure p1out is the uno and W emission parton.
  * @TODO: Include separate wrapper functions for forward and backward to clean up
  *        ME_W_unof_current in `MatrixElement.cc`.
  */
   double jWuno_j(HLV pg, HLV p1out, HLV plbar, HLV pl, HLV p1in,
                  HLV p2out, HLV p2in, bool aqlineb,
                  ParticleProperties const & wprop
     ){
     const auto helsum = aqlineb?
       jWuno_j_helsum<helicity::plus>:
       jWuno_j_helsum<helicity::minus>;
 
     //Helicity sum and average over initial states
     return helsum(pg, p1out,plbar,pl,p1in,p2out,p2in, wprop)/(4.*HEJ::C_A*HEJ::C_A);
   }
 }
 double ME_Wuno_qQ(HLV p1out, HLV p1in, HLV p2out, HLV p2in,
                   HLV pg, HLV plbar, HLV pl, ParticleProperties const & wprop
 ){
   return jWuno_j(pg, p1out, plbar, pl, p1in, p2out, p2in, false, wprop);
 }
 
 double ME_Wuno_qQbar(HLV p1out, HLV p1in, HLV p2out, HLV p2in,
                      HLV pg, HLV plbar, HLV pl,
                      ParticleProperties const & wprop
 ){
   return jWuno_j(pg, p1out, plbar, pl, p1in, p2out, p2in, false, wprop);
 }
 
 double ME_Wuno_qbarQ(HLV p1out, HLV p1in, HLV p2out, HLV p2in,
                      HLV pg, HLV plbar, HLV pl,
                      ParticleProperties const & wprop
 ){
   return jWuno_j(pg, p1out, plbar, pl, p1in, p2out, p2in, true, wprop);
 }
 
 double ME_Wuno_qbarQbar(HLV p1out, HLV p1in, HLV p2out, HLV p2in,
                         HLV pg, HLV plbar, HLV pl,
                         ParticleProperties const & wprop
 ){
   return jWuno_j(pg, p1out, plbar, pl, p1in, p2out, p2in, true, wprop);
 }
 
 double ME_Wuno_qg(HLV p1out, HLV p1in, HLV p2out, HLV p2in,
                   HLV pg, HLV plbar, HLV pl, ParticleProperties const & wprop
 ){
   return jWuno_j(pg, p1out, plbar, pl, p1in, p2out, p2in, false, wprop)
           *K_g(p2out, p2in)/HEJ::C_F;
 }
 
 double ME_Wuno_qbarg(HLV p1out, HLV p1in, HLV p2out, HLV p2in,
                      HLV pg, HLV plbar, HLV pl,
                      ParticleProperties const & wprop
 ){
   return jWuno_j(pg, p1out, plbar, pl, p1in, p2out, p2in, true, wprop)
           *K_g(p2out, p2in)/HEJ::C_F;
 }
 
 // helicity sum helper for jWqqx_j(...)
 template<Helicity h1>
 double jWqqx_j_helsum(
   HLV const & pg, HLV const & pq, HLV const & plbar, HLV const & pl,
   HLV const & pqbar, HLV const & p3, HLV const & pb,
   ParticleProperties const & wprop
 ){
   using helicity::minus;
   using helicity::plus;
 
   const double ME2h1pp = jM2_W_extremal_qqbar<h1, plus, plus>(
     pg, pq, plbar, pl, pqbar, p3, pb, wprop
   );
   const double ME2h1pm = jM2_W_extremal_qqbar<h1, plus, minus>(
     pg, pq, plbar, pl, pqbar, p3, pb, wprop
   );
   const double ME2h1mp = jM2_W_extremal_qqbar<h1, minus, plus>(
     pg, pq, plbar, pl, pqbar, p3, pb, wprop
   );
   const double ME2h1mm = jM2_W_extremal_qqbar<h1, minus, minus>(
     pg, pq, plbar, pl, pqbar, p3, pb, wprop
   );
 
   return ME2h1pp + ME2h1pm + ME2h1mp + ME2h1mm;
 }
 
 /**
  * @brief W+Jets Extremal qqx Contributions, function to handle all incoming types.
  * @param pgin              Incoming gluon which will split into qqx.
  * @param pqout             Quark of extremal qqx outgoing (W-Emission).
  * @param plbar             Outgoing anti-lepton momenta
  * @param pl                Outgoing lepton momenta
  * @param pqbarout          Anti-quark of extremal qqx pair. (W-Emission)
  * @param pout              Outgoing Particle 2 (end of FKL chain)
  * @param p2in              Incoming Particle 2
  * @param aqlinef           Bool. Is Forwards quark line an anti-quark line?
  *
  * Calculates j_W_{qqx} ^\mu    j_\mu. Ie, Ex-QQX with W emission same side.
  * Handles all possible incoming states. Calculated via crossing symmetry from jWuno_j.
  */
 double jWqqx_j(HLV pgin, HLV pqout, HLV plbar, HLV pl,
                HLV pqbarout, HLV p2out, HLV p2in, bool aqlinef,
                ParticleProperties const & wprop
 ){
   const auto helsum = aqlinef?
     jWqqx_j_helsum<helicity::plus>:
     jWqqx_j_helsum<helicity::minus>;
 
   //Helicity sum and average over initial states.
   double ME2 = helsum(pgin, pqout, plbar, pl, pqbarout, p2out, p2in, wprop)/
     (4.*HEJ::C_A*HEJ::C_A);
 
   //Correct colour averaging after crossing:
   ME2*=(3.0/8.0);
 
   return ME2;
 }
 
 double ME_WExqqx_qbarqQ(HLV pgin, HLV pqout, HLV plbar, HLV pl,
                       HLV pqbarout, HLV p2out, HLV p2in,
                ParticleProperties const & wprop
 ){
   return jWqqx_j(pgin, pqout, plbar, pl, pqbarout, p2out, p2in, false, wprop);
 }
 
 double ME_WExqqx_qqbarQ(HLV pgin, HLV pqbarout, HLV plbar, HLV pl,
                       HLV pqout, HLV p2out, HLV p2in,
                       ParticleProperties const & wprop
 ){
   return jWqqx_j(pgin, pqbarout, plbar, pl, pqout, p2out, p2in, true, wprop);
 }
 
 double ME_WExqqx_qbarqg(HLV pgin, HLV pqout, HLV plbar, HLV pl,
                       HLV pqbarout, HLV p2out, HLV p2in,
                       ParticleProperties const & wprop
 ){
   return jWqqx_j(pgin, pqout, plbar, pl, pqbarout, p2out, p2in, false, wprop)
           *K_g(p2out,p2in)/HEJ::C_F;
 }
 
 double ME_WExqqx_qqbarg(HLV pgin, HLV pqbarout, HLV plbar, HLV pl,
                       HLV pqout, HLV p2out, HLV p2in,
                       ParticleProperties const & wprop
 ){
   return jWqqx_j(pgin, pqbarout, plbar, pl, pqout, p2out, p2in, true, wprop)
           *K_g(p2out,p2in)/HEJ::C_F;
 }
 
 namespace {
   template<Helicity h1, Helicity hg>
   double jW_jqqbar(
     HLV const & pb,
     HLV const & p2,
     HLV const & p3,
     HLV const & pa,
     HLV const & p1,
     HLV const & pl,
     HLV const & plbar
   ) {
     using helicity::minus;
     using helicity::plus;
 
     static constexpr COM cm1m1 = 8./3.;
     static constexpr COM cm2m2 = 8./3.;
     static constexpr COM cm3m3 = 6.;
     static constexpr COM cm1m2 =-1./3.;
     static constexpr COM cm1m3 = COM{0.,-3.};
     static constexpr COM cm2m3 = COM{0.,3.};
 
     const COM m1 = HEJ::jW_qggm1<h1,hg>(pb,p2,p3,pa,p1,pl,plbar);
     const COM m2 = HEJ::jW_qggm2<h1,hg>(pb,p2,p3,pa,p1,pl,plbar);
     const COM m3 = HEJ::jW_qggm3<h1,hg>(pb,p2,p3,pa,p1,pl,plbar);
 
     return real(
       cm1m1*pow(abs(m1),2) + cm2m2*pow(abs(m2),2)
       + cm3m3*pow(abs(m3),2) + 2.*real(cm1m2*m1*conj(m2))
     )
       + 2.*real(cm1m3*m1*conj(m3))
       + 2.*real(cm2m3*m2*conj(m3)) ;
   }
 }
 
 // contraction of W current with extremal qqbar on the other side
 double ME_W_Exqqx_QQq(
   HLV pa, HLV pb,
   HLV p1,  HLV p2,
   HLV p3, HLV plbar, HLV pl, bool aqlinepa,
   ParticleProperties const & wprop
 ){
   using helicity::minus;
   using helicity::plus;
 
   const double WPropfact = WProp(plbar, pl, wprop);
   const double prefactor = 2.*WPropfact/24./4./(
     (pa-p1-pl-plbar).m2()*(p2+p3-pb).m2()
   );
   if(aqlinepa) {
     return prefactor*(
       jW_jqqbar<plus, minus>(pb,p2,p3,pa,p1,pl,plbar)
       + jW_jqqbar<plus, plus>(pb,p2,p3,pa,p1,pl,plbar)
     );
   }
   return prefactor*(
     jW_jqqbar<minus, minus>(pb,p2,p3,pa,p1,pl,plbar)
     + jW_jqqbar<minus, plus>(pb,p2,p3,pa,p1,pl,plbar)
   );
 }
 
 namespace {
   // helper function for matrix element for W + Jets with central qqbar
   template<HEJ::Helicity h1a, HEJ::Helicity h4b>
   double amp_WCenqqx_qq(
     HLV const & pa, HLV const &  p1,
     HLV const & pb, HLV const &  p4,
     HLV const &  pq, HLV const &  pqbar,
     HLV const &  pl, HLV const &  plbar,
     HLV const &  q11, HLV const &  q12
   ) {
     const COM sym = HEJ::M_sym_W<h1a, h4b>(
       pa, p1, pb, p4, pq, pqbar, pl, plbar, q11, q12
     );
     const COM cross = HEJ::M_cross_W<h1a, h4b>(
       pa, p1, pb, p4, pq, pqbar, pl, plbar, q11, q12
     );
     const COM uncross = HEJ::M_uncross_W<h1a, h4b>(
       pa, p1, pb, p4, pq, pqbar, pl, plbar, q11, q12
     );
 
     // Colour factors
     static constexpr COM cmsms = 3.;
     static constexpr COM cmumu = 4./3.;
     static constexpr COM cmcmc = 4./3.;
     static constexpr COM cmsmu = COM{0., 3./2.};
     static constexpr COM cmsmc = COM{0.,-3./2.};
     static constexpr COM cmumc = -1./6.;
 
     return real(
       cmsms*pow(abs(sym),2)
       +cmumu*pow(abs(uncross),2)
       +cmcmc*pow(abs(cross),2)
     )
       +2.*real(cmsmu*sym*conj(uncross))
       +2.*real(cmsmc*sym*conj(cross))
       +2.*real(cmumc*uncross*conj(cross))
       ;
   }
 }
 
 // matrix element for W + Jets with W emission off central qqbar
 double ME_WCenqqx_qq(
   HLV pa, HLV pb, HLV pl, HLV plbar, std::vector<HLV> partons,
   bool /* aqlinepa */, bool /* aqlinepb */, bool qqxmarker, int nabove,
   ParticleProperties const & wprop
 ) {
   using helicity::plus;
   using helicity::minus;
 
   CLHEP::HepLorentzVector q1 = pa;
   for(int i = 0; i <= nabove; ++i){
     q1 -= partons[i];
   }
   const auto qq = HEJ::split_into_lightlike(q1);
   // since q1.m2() < 0 the following assertion is always true
   // see documentation for split_into_lightlike
   assert(qq.second.e() < 0);
 
   HLV pq, pqbar;
   if (qqxmarker){
     pqbar = partons[nabove+1];
     pq = partons[nabove+2];}
   else{
     pq = partons[nabove+1];
     pqbar = partons[nabove+2];
   }
   const HLV p1 = partons.front();
   const HLV p4 = partons.back();
 
   // 4 Different Helicity Choices (Differs from Pure Jet Case, where there is
   // also the choice in qqbar helicity.
   // the first helicity label is for aqlinepa == true,
   // the second one for aqlinepb == true
   // In principle the corresponding helicity should be flipped
   // if either of them is false, but we sum up all helicities,
   // so this has no effect in the end.
   const double amp_mm = amp_WCenqqx_qq<minus, minus>(
     pa, p1, pb, p4, pq, pqbar, pl, plbar, qq.first, -qq.second
   );
   const double amp_mp = amp_WCenqqx_qq<minus, plus>(
     pa, p1, pb, p4, pq, pqbar, pl, plbar, qq.first, -qq.second
   );
   const double amp_pm = amp_WCenqqx_qq<plus, minus>(
     pa, p1, pb, p4, pq, pqbar, pl, plbar, qq.first, -qq.second
   );
   const double amp_pp = amp_WCenqqx_qq<plus, plus>(
     pa, p1, pb, p4, pq, pqbar, pl, plbar, qq.first, -qq.second
   );
 
   const double t1 = q1.m2();
   const double t3 = (q1-pl-plbar-pq-pqbar).m2();
 
   const double amp = WProp(plbar, pl, wprop)*(
     amp_mm+amp_mp+amp_pm+amp_pp
   )/(9.*4.*t1*t1*t3*t3);
 
   return amp;
 }
 
 // helper function for matrix element for W + Jets with central qqbar
 // W emitted off extremal parton
 // @TODO: code duplication with amp_WCenqqx_qq
 template<HEJ::Helicity h1a, HEJ::Helicity hqqbar>
 double amp_W_Cenqqx_qq(
     HLV const & pa, HLV const &  p1,
     HLV const & pb, HLV const &  pn,
     HLV const &  pq, HLV const &  pqbar,
     HLV const &  pl, HLV const &  plbar,
     HLV const &  q11, HLV const &  q12
   ) {
 
   const COM crossed = HEJ::M_cross<h1a, hqqbar>(
     pa, p1, pb, pn, pq, pqbar, pl, plbar, q11, q12
   );
   const COM uncrossed = HEJ::M_qbar<h1a, hqqbar>(
     pa, p1, pb, pn, pq, pqbar, pl, plbar, q11, q12
   );
   const COM sym = HEJ::M_sym<h1a, hqqbar>(
     pa, p1, pb, pn, pq, pqbar, pl, plbar, q11, q12
   );
 
   //Colour factors:
   static constexpr COM cmsms = 3.;
   static constexpr COM cmumu = 4./3.;
   static constexpr COM cmcmc = 4./3.;
   static constexpr COM cmsmu = COM{0.,3./2.};
   static constexpr COM cmsmc = COM{0.,-3./2.};
   static constexpr COM cmumc = -1./6.;
 
   return real(
     cmsms*pow(abs(sym),2)
     +cmumu*pow(abs(uncrossed),2)
     +cmcmc*pow(abs(crossed),2)
   )
     +2.*real(cmsmu*sym*conj(uncrossed))
     +2.*real(cmsmc*sym*conj(crossed))
     +2.*real(cmumc*uncrossed*conj(crossed))
     ;
 }
 
 // matrix element for W + Jets with W emission *not* off central qqbar
 double ME_W_Cenqqx_qq(
   HLV pa, HLV pb,HLV pl,HLV plbar, std::vector<HLV> partons,
   bool aqlinepa, bool aqlinepb, bool qqxmarker, int nabove,
   int nbelow, bool forwards, ParticleProperties const & wprop
 ){
   using helicity::minus;
   using helicity::plus;
 
   if (!forwards){ //If Emission from Leg a instead, flip process.
     std::swap(pa, pb);
     std::reverse(partons.begin(),partons.end());
     std::swap(aqlinepa, aqlinepb);
     qqxmarker = !qqxmarker;
     std::swap(nabove,nbelow);
   }
 
   HLV q1=pa;
   for(int i=0;i<nabove+1;++i){
     q1-=partons.at(i);
   }
   const auto qq = HEJ::split_into_lightlike(q1);
 
   HLV pq, pqbar;
   if (qqxmarker){
     pqbar = partons[nabove+1];
     pq = partons[nabove+2];}
   else{
     pq = partons[nabove+1];
     pqbar = partons[nabove+2];}
 
   // we assume that the W is emitted off a quark line
   // if this is not the case, we have to apply CP conjugation,
   // which is equivalent to swapping lepton and antilepton momenta
   if(aqlinepb) std::swap(pl, plbar);
 
   const HLV p1 = partons.front();
   const HLV pn = partons.back();
 
   // helicity labels are for aqlinepa == aqlineb == false,
   // In principle the helicities should be flipped
   // if either of them is true, but we sum up all helicities,
   // so this has no effect in the end.
   const double amp_mm = amp_W_Cenqqx_qq<minus, minus>(
     pa, p1, pb, pn, pq, pqbar, pl, plbar, qq.first, -qq.second
   );
   const double amp_mp = amp_W_Cenqqx_qq<minus, plus>(
     pa, p1, pb, pn, pq, pqbar, pl, plbar, qq.first, -qq.second
   );
   const double amp_pm = amp_W_Cenqqx_qq<plus, minus>(
     pa, p1, pb, pn, pq, pqbar, pl, plbar, qq.first, -qq.second
   );
   const double amp_pp = amp_W_Cenqqx_qq<plus, plus>(
     pa, p1, pb, pn, pq, pqbar, pl, plbar, qq.first, -qq.second
   );
 
   const double t1 = q1.m2();
   const double t3 = (q1 - pq - pqbar).m2();
 
   const double amp= WProp(plbar, pl, wprop)*(
     amp_mm+amp_mp+amp_pm+amp_pp
   )/(9.*4.*t1*t1*t3*t3);
 
   return amp;
 }