diff --git a/FixedOrderGen/src/PhaseSpacePoint.cc b/FixedOrderGen/src/PhaseSpacePoint.cc
index 63ac4df..523b7bd 100644
--- a/FixedOrderGen/src/PhaseSpacePoint.cc
+++ b/FixedOrderGen/src/PhaseSpacePoint.cc
@@ -1,455 +1,462 @@
 #include "PhaseSpacePoint.hh"
 
 #include <random>
 
 #include "RHEJ/kinematics.hh"
 #include "RHEJ/utility.hh"
 #include "RHEJ/exceptions.hh"
 
 #include "Process.hh"
 
 #include <CLHEP/Random/Randomize.h>
 #include <CLHEP/Random/RanluxEngine.h>
 
 using namespace RHEJ;
 
 namespace HEJFOG{
 
   static_assert(
       std::numeric_limits<double>::has_quiet_NaN,
       "no quiet NaN for double"
   );
   constexpr double NaN = std::numeric_limits<double>::quiet_NaN();
   RHEJ::UnclusteredEvent to_UnclusteredEvent(PhaseSpacePoint const & psp){
     RHEJ::UnclusteredEvent result;
     result.incoming = psp.incoming();
     std::sort(
         begin(result.incoming), end(result.incoming),
         [](Particle o1, Particle o2){return o1.p.pz()<o2.p.pz();}
     );
     assert(result.incoming.size() == 2);
     result.outgoing = psp.outgoing();
     assert(
         std::is_sorted(
             begin(result.outgoing), end(result.outgoing),
             RHEJ::rapidity_less{}
         )
     );
     assert(result.outgoing.size() >= 2);
     result.decays = psp.decays();
     result.central.mur = NaN;
     result.central.muf = NaN;
     result.central.weight = psp.weight();
     return result;
   }
 
   namespace{
     bool can_swap_to_uno(
         RHEJ::Particle const & p1, RHEJ::Particle const & p2
     ){
       return is_parton(p1)
         && p1.type != RHEJ::pid::gluon
         && p2.type == RHEJ::pid::gluon;
     }
   }
 
   void PhaseSpacePoint::maybe_turn_to_uno(
       double chance,
       RHEJ::RNG & ran
   ){
     assert(outgoing_.size() >= 2);
     const size_t nout = outgoing_.size();
     const bool can_be_uno_backward = can_swap_to_uno(
         outgoing_[0], outgoing_[1]
     );
     const bool can_be_uno_forward = can_swap_to_uno(
         outgoing_[nout-1], outgoing_[nout-2]
     );
     if(!can_be_uno_backward && !can_be_uno_forward) return;
     if(ran.flat() < chance){
       weight_ /= chance;
       if(can_be_uno_backward && can_be_uno_forward){
         if(ran.flat() < 0.5){
           std::swap(outgoing_[0].type, outgoing_[1].type);
         }
         else{
           std::swap(outgoing_[nout-1].type, outgoing_[nout-2].type);
         }
         weight_ *= 2.;
       }
       else if(can_be_uno_backward){
         std::swap(outgoing_[0].type, outgoing_[1].type);
       }
       else{
         assert(can_be_uno_forward);
         std::swap(outgoing_[nout-1].type, outgoing_[nout-2].type);
       }
     }
     else weight_ /= 1 - chance;
   }
 
   PhaseSpacePoint::PhaseSpacePoint(
     Process const & proc,
     JetParameters const & jet_param,
     RHEJ::PDF & pdf, double E_beam,
     double uno_chance,
     HiggsProperties const & h,
     RHEJ::RNG & ran
   )
   {
     assert(proc.njets >= 2);
     const int nout = proc.njets + (proc.boson?1:0);
    status_ = good;
    weight_ = 1;
    weight_ /= std::tgamma(nout);
 
    outgoing_.reserve(nout);
 
    for(auto&& p_out: gen_LO_partons(proc.njets, jet_param, E_beam, ran)){
      outgoing_.emplace_back(Particle{pid::gluon, std::move(p_out)});
    }
    if(status_ != good) return;
 
    if(proc.boson && *proc.boson == pid::Higgs){
      // The Higgs
      auto Hparticle=gen_boson(pid::higgs, h.mass, h.width, ran);
      auto pos=std::upper_bound(
          begin(outgoing_),end(outgoing_),Hparticle,rapidity_less{}
      );
      outgoing_.insert(pos, Hparticle);
      if(! h.decays.empty()){
        const int boson_idx = std::distance(begin(outgoing_), pos);
        decays_.emplace(
            boson_idx,
            decay_boson(outgoing_[boson_idx], h.decays, ran)
        );
      }
    }
 
    reconstruct_incoming(proc.incoming, pdf, E_beam, jet_param.min_pt, ran);
    if(status_ != good) return;
    // set outgoing states
    most_backward_FKL(outgoing_).type = incoming_[0].type;
    most_forward_FKL(outgoing_).type = incoming_[1].type;
 
    if(proc.njets > 2) maybe_turn_to_uno(uno_chance, ran);
   }
 
   double PhaseSpacePoint::gen_hard_pt(
       int np , double ptmin, double ptmax, double y,
       RHEJ::RNG & ran
   ) {
     // heuristic parameters for pt sampling
     const double ptpar = ptmin + np/5.;
     const double arg_small_y = atan((ptmax - ptmin)/ptpar);
     const double y_cut = 3.;
 
     const double r1 = ran.flat();
     if(y < y_cut){
       const double pt = ptmin + ptpar*tan(r1*arg_small_y);
       const double temp = cos(r1*arg_small_y);
       weight_ *= pt*ptpar*arg_small_y/(temp*temp);
       return pt;
     }
 
     const double ptpar2 = ptpar/(1 + 5*(y-y_cut));
     const double temp = 1. - std::exp((ptmin-ptmax)/ptpar2);
     const double pt = ptmin - ptpar2*std::log(1-r1*temp);
     weight_ *= pt*ptpar2*temp/(1-r1*temp);
     return pt;
   }
 
   double PhaseSpacePoint::gen_soft_pt(int np, double max_pt, RHEJ::RNG & ran) {
     constexpr double ptpar = 4.;
 
     const double r = ran.flat();
     weight_ *= ptpar/(np*r);
     return max_pt + ptpar/np*std::log(r);
   }
 
   double PhaseSpacePoint::gen_parton_pt(
       int count, JetParameters const & jet_param, double max_pt, double y,
       RHEJ::RNG & ran
   ) {
     constexpr double p_small_pt = 0.02;
 
     if(! jet_param.peak_pt) {
        return gen_hard_pt(count, jet_param.min_pt, max_pt, y, ran);
     }
     const double r = ran.flat();
     if(r > p_small_pt) {
       weight_ /= 1. - p_small_pt;
       return gen_hard_pt(count, *jet_param.peak_pt, max_pt, y, ran);
     }
     weight_ /= p_small_pt;
-    return gen_soft_pt(count, *jet_param.peak_pt, ran);
+    const double pt =  gen_soft_pt(count, *jet_param.peak_pt, ran);
+    if(pt < jet_param.min_pt) {
+      weight_=0.0;
+      status_ = not_enough_jets;
+      return jet_param.min_pt;
+    }
+    return pt;
   }
 
   std::vector<fastjet::PseudoJet> PhaseSpacePoint::gen_LO_partons(
       int np ,
       JetParameters const & jet_param,
       double max_pt,
       RHEJ::RNG & ran
   ){
     if (np<2) throw std::invalid_argument{"Not enough partons in gen_LO_partons"};
 
     weight_ /= pow(16.*pow(M_PI,3),np-2);
     std::vector<fastjet::PseudoJet> partons;
     partons.reserve(np);
     for(int i = 0; i < np; ++i){
       const double y = -jet_param.max_y + 2*jet_param.max_y*ran.flat();
       weight_ *= 2*jet_param.max_y;
 
       const double phi = 2*M_PI*ran.flat();
       weight_ *= 2.0*M_PI;
 
       const double pt = gen_parton_pt(np, jet_param, max_pt, y, ran);
+      if(weight_ == 0.0) return {};
 
       partons.emplace_back(fastjet::PtYPhiM(pt, y, phi));
-      assert(jet_param.min_pt-1e-5 <= partons[i].pt());
+      assert(jet_param.min_pt <= partons[i].pt());
       assert(partons[i].pt() <= max_pt+1e-5);
     }
     // Need to check that at LO, the number of jets = number of partons;
     fastjet::ClusterSequence cs(partons, jet_param.def);
     auto cluster_jets=cs.inclusive_jets(jet_param.min_pt);
     if (cluster_jets.size()!=unsigned(np)){
       weight_=0.0;
       status_ = not_enough_jets;
       return {};
     }
 
     std::sort(begin(partons), end(partons), rapidity_less{});
 
     return partons;
   }
 
   Particle PhaseSpacePoint::gen_boson(
       RHEJ::ParticleID bosonid, double mass, double width,
       RHEJ::RNG & ran
   ){
     std::array<double,2> ptrans{0.,0.};
     for (auto const & parton:outgoing_) {
       ptrans[0]-=parton.px();
       ptrans[1]-=parton.py();
     }
 
     // The Higgs:
     // Generate a y Gaussian distributed around 0
     const double y = random_normal(1.6, ran);
     const double r1 = ran.flat();
     const double sH = mass*(
         mass + width*tan(M_PI/2.*r1 + (r1-1.)*atan(mass/width))
     );
 
     const double mHperp=sqrt(ptrans[0]*ptrans[0]+ptrans[1]*ptrans[1]+sH);
     const double pz=mHperp*sinh(y);
     const double E=mHperp*cosh(y);
 
     return Particle{bosonid,fastjet::PseudoJet{ptrans[0],ptrans[1],pz,E}};
   }
 
   Particle const & PhaseSpacePoint::most_backward_FKL(
       std::vector<Particle> const & partons
   ) const{
     if(!RHEJ::is_parton(partons[0])) return partons[1];
     return partons[0];
   }
 
   Particle const & PhaseSpacePoint::most_forward_FKL(
       std::vector<Particle> const & partons
   ) const{
     const size_t last_idx = partons.size() - 1;
     if(!RHEJ::is_parton(partons[last_idx])) return partons[last_idx-1];
     return partons[last_idx];
   }
 
   Particle & PhaseSpacePoint::most_backward_FKL(
       std::vector<Particle> & partons
   ) const{
     if(!RHEJ::is_parton(partons[0])) return partons[1];
     return partons[0];
   }
 
   Particle & PhaseSpacePoint::most_forward_FKL(
       std::vector<Particle> & partons
   ) const{
     const size_t last_idx = partons.size() - 1;
     if(!RHEJ::is_parton(partons[last_idx])) return partons[last_idx-1];
     return partons[last_idx];
   }
 
   void PhaseSpacePoint::reconstruct_incoming(
       std::array<RHEJ::ParticleID, 2> const & ids,
       RHEJ::PDF & pdf, double E_beam,
       double uf,
       RHEJ::RNG & ran
   ){
     std::tie(incoming_[0].p, incoming_[1].p) = incoming_momenta(outgoing_);
     // calculate xa, xb
     const double sqrts=2*E_beam;
     const double xa=(incoming_[0].p.e()-incoming_[0].p.pz())/sqrts;
     const double xb=(incoming_[1].p.e()+incoming_[1].p.pz())/sqrts;
     // abort if phase space point is outside of collider energy reach
     if (xa>1. || xb>1.){
       weight_=0;
       status_ = too_much_energy;
       return;
     }
     // pick pdfs
     /** TODO:
      *  ufa, ufb don't correspond to our final scale choice.
      *  The reversed HEJ scale generators currently expect a full event as input,
      *  so fixing this is not completely trivial
      */
     if(ids[0] == pid::proton || ids[0] == pid::p_bar){
       const double ufa=uf;
       incoming_[0].type = generate_incoming_id(xa, ufa, pdf, ran);
     }
     else {
       incoming_[0].type = ids[0];
     }
     if(ids[1] == pid::proton || ids[1] == pid::p_bar){
       const double ufb=uf;
       incoming_[1].type = generate_incoming_id(xb, ufb, pdf, ran);
     }
     else {
       incoming_[1].type = ids[1];
     }
     assert(momentum_conserved(1e-7));
   }
 
   RHEJ::ParticleID PhaseSpacePoint::generate_incoming_id(
       double x, double uf, RHEJ::PDF & pdf,
       RHEJ::RNG & ran
   ){
     const double pdfg=fabs(pdf.pdfpt(0,x,uf,pid::gluon));
     const double pdfu=fabs(pdf.pdfpt(0,x,uf,pid::up));
     const double pdfd=fabs(pdf.pdfpt(0,x,uf,pid::down));
     const double pdfux=fabs(pdf.pdfpt(0,x,uf,pid::u_bar));
     const double pdfdx=fabs(pdf.pdfpt(0,x,uf,pid::d_bar));
     const double pdfc=fabs(pdf.pdfpt(0,x,uf,pid::charm));
     const double pdfs=fabs(pdf.pdfpt(0,x,uf,pid::strange));
     const double pdfsx=fabs(pdf.pdfpt(0,x,uf,pid::s_bar));
     const double pdfb=fabs(pdf.pdfpt(0,x,uf,pid::b));
 
     const double pdftot=pdfg+4.0/9.0*(pdfu + pdfd + pdfux + pdfdx +pdfs +pdfsx + 2.0*(pdfc +pdfb ));
     const double r1=pdftot*ran.flat();
     double sum;
 
     if (r1<(sum=pdfg)) {
       weight_*=pdftot/pdfg;
       return pid::gluon;
     }
     if (r1<(sum+=(4./9.)*pdfu)) {
       weight_*=pdftot/((4./9.)*pdfu);
       return pid::up;
     }
     else if (r1<(sum+=(4./9.)*pdfd)) {
       weight_*=pdftot/((4./9.)*pdfd);
       return pid::down;
     }
     else if (r1<(sum+=(4./9.)*pdfux)) {
       weight_*=pdftot/((4./9.)*pdfux);
       return pid::u_bar;
     }
     else if (r1<(sum+=(4./9.)*pdfdx)) {
       weight_*=pdftot/((4./9.)*pdfdx);
       return pid::d_bar;
     }
     else if (r1<(sum+=(4./9.)*pdfc)) {
       weight_*=pdftot/((4./9.)*pdfc);
       return pid::c;
     }
     else if (r1<(sum+=(4./9.)*pdfc)){
       weight_*=pdftot/((4./9.)*pdfc);
       return pid::c_bar;
     }
     else if (r1<(sum+=(4./9.)*pdfs)) {
       weight_*=pdftot/((4./9.)*pdfs);
       return pid::s;
     }
     else if (r1<(sum+=(4./9.)*pdfsx)) {
       weight_*=pdftot/((4./9.)*pdfsx);
       return pid::s_bar;
     }
     else if (r1<(sum+=(4./9.)*pdfb)) {
       weight_*=pdftot/((4./9.)*pdfb);
       return pid::b;
     }
     else if (r1<=(sum+=(4./9.)*pdfb)) {
       weight_*=pdftot/((4./9.)*pdfb);
       return pid::b_bar;
     }
     std::cout << "Error in choosing incoming parton: "<<x<<" "<<uf<<" "<<sum<<" "<<pdftot<<" "<<r1;
     std::cout << " "<<pdfg+4./9.*(pdfu+pdfux+pdfd+pdfdx+pdfs+pdfsx+2.*(pdfc+pdfb))<<std::endl;
     throw std::logic_error{"Failed to choose parton flavour"};
   }
 
   double PhaseSpacePoint::random_normal(
       double stddev,
       RHEJ::RNG & ran
   ){
     const double r1 = ran.flat();
     const double r2 = ran.flat();
     const double lninvr1 = -log(r1);
     const double result = stddev*sqrt(2.*lninvr1)*cos(2.*M_PI*r2);
     weight_ *= exp(result*result/(2*stddev*stddev))*sqrt(2.*M_PI)*stddev;
     return result;
   }
 
   bool PhaseSpacePoint::momentum_conserved(double ep) const{
     fastjet::PseudoJet diff;
     for(auto const & in: incoming()) diff += in.p;
     for(auto const & out: outgoing()) diff -= out.p;
     return nearby_ep(diff, fastjet::PseudoJet{}, ep);
   }
 
   Decay PhaseSpacePoint::select_decay_channel(
       std::vector<Decay> const & decays,
       RHEJ::RNG & ran
   ){
     double br_total = 0.;
     for(auto const & decay: decays) br_total += decay.branching_ratio;
     // adjust weight
     // this is given by (channel branching ratio)/(chance to pick channel)
     // where (chance to pick channel) =
     //       (channel branching ratio)/(total branching ratio)
     weight_ *= br_total;
     const double r1 = br_total*ran.flat();
     double br_sum = 0.;
     for(auto const & decay: decays){
       br_sum += decay.branching_ratio;
       if(r1 < br_sum) return decay;
     }
     throw std::logic_error{"unreachable"};
   }
 
   std::vector<Particle> PhaseSpacePoint::decay_boson(
       RHEJ::Particle const & parent,
       std::vector<Decay> const & decays,
       RHEJ::RNG & ran
   ){
     const auto channel = select_decay_channel(decays, ran);
     if(channel.products.size() != 2){
       throw RHEJ::not_implemented{
         "only decays into two particles are implemented"
       };
     }
     std::vector<Particle> decay_products(channel.products.size());
     for(size_t i = 0; i < channel.products.size(); ++i){
       decay_products[i].type = channel.products[i];
     }
     // choose polar and azimuth angle in parent rest frame
     const double E = parent.m()/2;
     const double theta = 2.*M_PI*ran.flat();
     const double cos_phi = 2.*ran.flat()-1.;
     const double sin_phi = sqrt(1. - cos_phi*cos_phi);  // Know 0 < phi < pi
     const double px = E*cos(theta)*sin_phi;
     const double py = E*sin(theta)*sin_phi;
     const double pz = E*cos_phi;
     decay_products[0].p.reset(px, py, pz, E);
     decay_products[1].p.reset(-px, -py, -pz, E);
     for(auto & particle: decay_products) particle.p.boost(parent.p);
     return decay_products;
   }
 }