Beispiel #1
0
StatusCode EDMToHepMCConverter::execute() {

  const fcc::MCParticleCollection* particles = m_genphandle.get();
  // ownership of event given to data service at the end of execute
  HepMC::GenEvent* event = new HepMC::GenEvent;

  // conversion of units to EDM standard units:
  // First cover the case that hepMC file is not in expected units and then convert to EDM default
  double hepmc2EdmLength = conversion_factor(event->length_unit(), gen::hepmcdefault::length) * gen::hepmc2edm::length;
  double hepmc2EdmEnergy =
      conversion_factor(event->momentum_unit(), gen::hepmcdefault::energy) * gen::hepmc2edm::energy;

  for (auto p : *(particles)) {
    if (p.status() == 1) {  // only final state particles
      GenParticle* pHepMC =
          new GenParticle(HepMC::FourVector(p.p4().px, p.p4().py, p.p4().pz, p.p4().mass / hepmc2EdmEnergy),
                          p.pdgId(),
                          p.status());  // hepmc status code for final state particle

      fcc::ConstGenVertex vStart = p.startVertex();
      if (p.startVertex().isAvailable()) {
        HepMC::GenVertex* v =
            new HepMC::GenVertex(HepMC::FourVector(vStart.position().x / hepmc2EdmLength,
                                                   vStart.position().y / hepmc2EdmLength,
                                                   vStart.position().z / hepmc2EdmLength,
                                                   vStart.ctau() / Gaudi::Units::c_light / hepmc2EdmLength));

        v->add_particle_out(pHepMC);
        event->add_vertex(v);
      }
    }
  }

  m_hepmchandle.put(event);
  return StatusCode::SUCCESS;
}
Beispiel #2
0
StatusCode ConstPtParticleGun::getNextEvent(HepMC::GenEvent& theEvent) {
  Gaudi::LorentzVector theFourMomentum;
  Gaudi::LorentzVector origin;
  // note: pgdid is set in function generateParticle
  int thePdgId;
  generateParticle(theFourMomentum, origin, thePdgId);

  // create HepMC Vertex --
  // by calling add_vertex(), the hepmc event is given ownership of the vertex
  HepMC::GenVertex* v = new HepMC::GenVertex(HepMC::FourVector(origin.X(), origin.Y(), origin.Z(), origin.T()));
  // create HepMC particle --
  // by calling add_particle_out(), the hepmc vertex is given ownership of the particle
  HepMC::GenParticle* p = new HepMC::GenParticle(
      HepMC::FourVector(theFourMomentum.Px(), theFourMomentum.Py(), theFourMomentum.Pz(), theFourMomentum.E()),
      thePdgId,
      1);  // hepmc status code for final state particle

  v->add_particle_out(p);

  theEvent.add_vertex(v);
  theEvent.set_signal_process_vertex(v);

  return StatusCode::SUCCESS;
}
Beispiel #3
0
int PHSartre::process_event(PHCompositeNode *topNode) {

  if (verbosity > 1) cout << "PHSartre::process_event - event: " << _eventcount << endl;
  
  bool passedTrigger = false;
  Event *event = NULL;

  TLorentzVector *eIn     = NULL;
  TLorentzVector *pIn     = NULL;
  TLorentzVector *eOut    = NULL;
  TLorentzVector *gamma   = NULL;
  TLorentzVector *vm      = NULL;
  TLorentzVector *PomOut  = NULL;
  TLorentzVector *pOut    = NULL;
  TLorentzVector *vmDecay1 = NULL; 
  TLorentzVector *vmDecay2 = NULL; 
  unsigned int preVMDecaySize = 0; 

  while (!passedTrigger) {
    ++_gencount;

    // Generate a Sartre event
    event = _sartre->generateEvent();
        
    //
    //  If Sartre is run in UPC mode, half of the events needs to be
    //  rotated around and axis perpendicular to z:
    //  (only for symmetric events)
    //
    if(settings->UPC() and settings->A()==settings->UPCA()){
      randomlyReverseBeams(event);
    }
	
    // for sPHENIX/RHIC p+Au
    // (see comments in ReverseBeams)
    // reverse when the proton emits the virtual photon
	
    if(settings->UPC() and settings->A()==197){
      ReverseBeams(event);
    }

    // Set pointers to the parts of the event we will need:

    eIn     = &event->particles[0].p;
    pIn     = &event->particles[1].p;
    eOut    = &event->particles[2].p;
    gamma   = &event->particles[3].p;
    vm      = &event->particles[4].p;
    PomOut  = &event->particles[5].p;
    pOut    = &event->particles[6].p;

    // To allow the triggering to work properly, we need to decay the vector meson here

    preVMDecaySize = event->particles.size(); 

    if(doPerformDecay) {

      if( decay->SetDecay(*vm, 2, daughterMasses) ){
	double weight = decay->Generate(); // weight is always 1 here
	if ( (weight-1) > FLT_EPSILON) {
	  cout << "PHSartre: Warning decay weight != 1, weight = " << weight << endl;
	}
	TLorentzVector *vmDaughter1 = decay->GetDecay(0);
	TLorentzVector *vmDaughter2 = decay->GetDecay(1);

	event->particles[4].status = 2; // set VM status

	Particle vmDC1; 
	vmDC1.index = event->particles.size(); 
	vmDC1.pdgId =  daughterID; 
	vmDC1.status = 1; // final state
	vmDC1.p = *vmDaughter1; 
	vmDC1.parents.push_back(4);	
	event->particles.push_back(vmDC1); 
	vmDecay1 = &event->particles[event->particles.size()-1].p;

	Particle vmDC2; 
	vmDC2.index = event->particles.size(); 
	vmDC2.pdgId =  -daughterID; 
	vmDC2.status = 1; // final state
	vmDC2.p = *vmDaughter2; 
	vmDC2.parents.push_back(4);	
	event->particles.push_back(vmDC2); 
	vmDecay2 = &event->particles[event->particles.size()-1].p;

      }
      else {
	cout << "PHSartre: WARNING: Kinematics of Vector Meson does not allow decay!" << endl;
      }

    }

    // test trigger logic
    
    bool andScoreKeeper = true;
    if (verbosity > 2) {
      cout << "PHSartre::process_event - triggersize: " << _registeredTriggers.size() << endl;
    }

    for (unsigned int tr = 0; tr < _registeredTriggers.size(); tr++) { 
      bool trigResult = _registeredTriggers[tr]->Apply(event);

      if (verbosity > 2) {
	cout << "PHSartre::process_event trigger: "
	     << _registeredTriggers[tr]->GetName() << "  " << trigResult << endl;
      }

      if (_triggersOR && trigResult) {
	passedTrigger = true;
	break;
      } else if (_triggersAND) {
	andScoreKeeper &= trigResult;
      }
      
      if (verbosity > 2 && !passedTrigger) {
	cout << "PHSartre::process_event - failed trigger: "
	     << _registeredTriggers[tr]->GetName() <<  endl;
      }
    }

    if ((andScoreKeeper && _triggersAND) || (_registeredTriggers.size() == 0)) {
      passedTrigger = true;
    }

  }

  // fill HepMC object with event
  
  HepMC::GenEvent *genevent = new HepMC::GenEvent(HepMC::Units::GEV, HepMC::Units::MM);

  // add some information to the event
  genevent->set_event_number(_eventcount);

  // Set the PDF information
  HepMC::PdfInfo pdfinfo;
  pdfinfo.set_scalePDF(event->Q2);
  genevent->set_pdf_info(pdfinfo); 

  // We would also like to save:
  //
  // event->t;
  // event->x;
  // event->y;
  // event->s;
  // event->W;
  // event->xpom;
  // (event->polarization == transverse ? 0 : 1);
  // (event->diffractiveMode == coherent ? 0 : 1);
  // 
  // but there doesn't seem to be a good place to do so 
  // within the HepMC event information?
  //
  // t, W and Q^2 form a minial set of good variables for diffractive events
  // Maybe what I do is record the input particles to the event at the HepMC
  // vertices and reconstruct the kinematics from there? 
  
  // Create HepMC vertices and add final state particles to them

  // First, the emitter(electron)-virtual photon vertex:

  HepMC::GenVertex* egammavtx = new HepMC::GenVertex(CLHEP::HepLorentzVector(0.0,0.0,0.0,0.0));
  genevent->add_vertex(egammavtx); 

  egammavtx->add_particle_in( 
			 new HepMC::GenParticle( CLHEP::HepLorentzVector(eIn->Px(),
									 eIn->Py(),
									 eIn->Pz(),
									 eIn->E()), 
						 event->particles[0].pdgId, 
						 3 ) 
			  );

  HepMC::GenParticle *hgamma =  new HepMC::GenParticle( CLHEP::HepLorentzVector(gamma->Px(),
									 gamma->Py(),
									 gamma->Pz(),
									 gamma->E()), 
						event->particles[3].pdgId, 
						3 ); 

  egammavtx->add_particle_out(hgamma);

  egammavtx->add_particle_out( 
			 new HepMC::GenParticle( CLHEP::HepLorentzVector(eOut->Px(),
									 eOut->Py(),
									 eOut->Pz(),
									 eOut->E()), 
						 event->particles[2].pdgId, 
						 1 ) 
			  );

  // Next, the hadron-pomeron vertex:

  HepMC::GenVertex* ppomvtx = new HepMC::GenVertex(CLHEP::HepLorentzVector(0.0,0.0,0.0,0.0));
  genevent->add_vertex(ppomvtx); 


  ppomvtx->add_particle_in( 
			 new HepMC::GenParticle( CLHEP::HepLorentzVector(pIn->Px(),
									 pIn->Py(),
									 pIn->Pz(),
									 pIn->E()), 
						 event->particles[1].pdgId, 
						 3 ) 
			     );

  HepMC::GenParticle *hPomOut = new HepMC::GenParticle( CLHEP::HepLorentzVector(PomOut->Px(),
									 PomOut->Py(),
									 PomOut->Pz(),
									 PomOut->E()), 
						 event->particles[5].pdgId, 
						 3 ); 

  ppomvtx->add_particle_out(hPomOut); 

  // If this is a nuclear breakup, add in the nuclear fragments
  // Otherwise, add in the outgoing hadron
        
  //If the event is incoherent, and nuclear breakup is enabled, fill the remnants to the tree
  if(settings->enableNuclearBreakup() and event->diffractiveMode == incoherent){
    for(unsigned int iParticle=7; iParticle < preVMDecaySize; iParticle++){
      if(event->particles[iParticle].status == 1) {  // Final-state particle
	const Particle& particle = event->particles[iParticle];	  
	ppomvtx->add_particle_out( 
			       new HepMC::GenParticle( CLHEP::HepLorentzVector(particle.p.Px(),
								 particle.p.Py(),
								 particle.p.Pz(),
								 particle.p.E()), 
						particle.pdgId, 
						1 ) 
				);
      }  
    }  
  }
  else{

    ppomvtx->add_particle_out( 
			      new HepMC::GenParticle( CLHEP::HepLorentzVector(pOut->Px(),
									      pOut->Py(),
									      pOut->Pz(),
									      pOut->E()), 
						      event->particles[6].pdgId, 
						      1 ) 
			       );
  }

  // The Pomeron-Photon vertex

  HepMC::GenVertex* gammapomvtx = new HepMC::GenVertex(CLHEP::HepLorentzVector(0.0,0.0,0.0,0.0));
  genevent->add_vertex(gammapomvtx); 
  
  gammapomvtx->add_particle_in(hgamma); 
  gammapomvtx->add_particle_in(hPomOut); 

  int isVMFinal = 1; 
  if(doPerformDecay) isVMFinal = 2; 

  HepMC::GenParticle *hvm = new HepMC::GenParticle( CLHEP::HepLorentzVector(vm->Px(),
									    vm->Py(),
									    vm->Pz(),
									    vm->E()), 
						   event->particles[4].pdgId, 
						   isVMFinal ) ; 

  gammapomvtx->add_particle_out( hvm );
 
  // Add the VM decay to the event

  if(doPerformDecay) {

    if(vmDecay1 && vmDecay2){

      HepMC::GenVertex* fvtx = new HepMC::GenVertex(CLHEP::HepLorentzVector(0.0,0.0,0.0,0.0));
      genevent->add_vertex(fvtx); 

      fvtx->add_particle_in( hvm ); 

      fvtx->add_particle_out( 
			 new HepMC::GenParticle( CLHEP::HepLorentzVector(vmDecay1->Px(),
							   vmDecay1->Py(),
							   vmDecay1->Pz(),
							   vmDecay1->E()), 
					  daughterID, 
					  1 ) 
			  );
      fvtx->add_particle_out( 
			 new HepMC::GenParticle( CLHEP::HepLorentzVector(vmDecay2->Px(),
							   vmDecay2->Py(),
							   vmDecay2->Pz(),
							   vmDecay2->E()), 
					  -daughterID, 
					  1 ) 
			  );

    }
    else {
      cout << "PHSartre: WARNING: Kinematics of Vector Meson does not allow decay!" << endl;
    }

  }

  // pass HepMC to PHNode
  
  PHHepMCGenEvent * success = hepmc_helper . insert_event(genevent);
  if (!success) {
    cout << "PHSartre::process_event - Failed to add event to HepMC record!" << endl;
    return Fun4AllReturnCodes::ABORTRUN;
  }


  // print outs
  
  if (verbosity > 2) cout << "PHSartre::process_event - FINISHED WHOLE EVENT" << endl;

  ++_eventcount;
  return Fun4AllReturnCodes::EVENT_OK;
}
Beispiel #4
0
bool HepMC2_Interface::Sherpa2HepMC(ATOOLS::Blob_List *const blobs,
                                    HepMC::GenEvent& event, double weight)
{
#ifdef USING__HEPMC2__UNITS
  event.use_units(HepMC::Units::GEV,
                  HepMC::Units::MM);
#endif
  event.set_event_number(ATOOLS::rpa->gen.NumberOfGeneratedEvents());
  size_t decid(11);
  std::map<size_t,size_t> decids;
  Blob *sp(blobs->FindFirst(btp::Signal_Process));
  if (sp) {
    Blob_Data_Base *info((*sp)["Decay_Info"]);
    if (info) {
      DecayInfo_Vector decs(info->Get<DecayInfo_Vector>());
      for (size_t i(0);i<decs.size();++i) decids[decs[i]->m_id]=++decid;
    }
  }
  m_blob2genvertex.clear();
  m_particle2genparticle.clear();
  HepMC::GenVertex * vertex;
  std::vector<HepMC::GenParticle*> beamparticles;
  for (ATOOLS::Blob_List::iterator blit=blobs->begin();
       blit!=blobs->end();++blit) {
    if (Sherpa2HepMC(*(blit),vertex,decids)) {
      event.add_vertex(vertex);
      if ((*blit)->Type()==ATOOLS::btp::Signal_Process) {
        if ((**blit)["NLO_subeventlist"]) {
          THROW(fatal_error,"Events containing correlated subtraction events"
                +std::string(" cannot be translated into the full HepMC event")
                +std::string(" format.\n")
                +std::string("   Try 'EVENT_OUTPUT=HepMC_Short' instead."));
        }
        event.set_signal_process_vertex(vertex);
        if((*blit)->NInP()==2) {
          kf_code fl1=(*blit)->InParticle(0)->Flav().HepEvt();
          kf_code fl2=(*blit)->InParticle(1)->Flav().HepEvt();
          double x1=(*blit)->InParticle(0)->Momentum()[0]/rpa->gen.PBeam(0)[0];
          double x2=(*blit)->InParticle(1)->Momentum()[0]/rpa->gen.PBeam(1)[0];
          double q(0.0), p1(0.0), p2(0.0);
          Blob_Data_Base *facscale((**blit)["Factorisation_Scale"]);
	  if (facscale) q=sqrt(facscale->Get<double>());
	  Blob_Data_Base *xf1((**blit)["XF1"]);
          Blob_Data_Base *xf2((**blit)["XF2"]);
          if (xf1) p1=xf1->Get<double>();
          if (xf2) p2=xf2->Get<double>();
	  HepMC::PdfInfo pdfinfo(fl1, fl2, x1, x2, q, p1, p2);
          event.set_pdf_info(pdfinfo);
        }
      }
      else if ((*blit)->Type()==ATOOLS::btp::Beam || 
	       (*blit)->Type()==ATOOLS::btp::Bunch) {
        for (HepMC::GenVertex::particles_in_const_iterator 
	       pit=vertex->particles_in_const_begin();
             pit!=vertex->particles_in_const_end(); ++pit) {
          if ((*pit)->production_vertex()==NULL) {
            beamparticles.push_back(*pit);
          }
        }
      }
    }
  }
  if (beamparticles.size()==2) {
    event.set_beam_particles(beamparticles[0],beamparticles[1]);
  }
  std::vector<double> weights;
  weights.push_back(weight);
  if (sp) {
    Blob_Data_Base *info((*sp)["MEWeight"]);
    if (!info) THROW(fatal_error,"Missing weight info.");
    double meweight(info->Get<double>());
    weights.push_back(meweight);
    Blob_Data_Base *ofni((*sp)["Weight_Norm"]);
    if (!ofni) THROW(fatal_error,"Missing weight normalisation.");
    double weightnorm(ofni->Get<double>());
    weights.push_back(weightnorm);
    ofni=(*sp)["Trials"];
    if (!ofni) THROW(fatal_error,"Missing nof trials.");
    double trials(ofni->Get<double>());
    weights.push_back(trials);
  }
  event.weights()=weights;
  return true;
}
Beispiel #5
0
bool HepMC2_Interface::Sherpa2ShortHepMC(ATOOLS::Blob_List *const blobs,
                                         HepMC::GenEvent& event, double weight)
{
#ifdef USING__HEPMC2__UNITS
  event.use_units(HepMC::Units::GEV,
                  HepMC::Units::MM);
#endif
  event.set_event_number(ATOOLS::rpa->gen.NumberOfGeneratedEvents());
  HepMC::GenVertex * vertex=new HepMC::GenVertex();
  std::vector<HepMC::GenParticle*> beamparticles;
  std::vector<std::pair<HepMC::FourVector,int> > beamparts,
                                                 remnantparts1, remnantparts2;
  Blob *sp(blobs->FindFirst(btp::Signal_Process));
  NLO_subevtlist* subevtlist(NULL);
  ME_wgtinfo* wgtinfo(0);
  
  if (sp) {
    Blob_Data_Base* seinfo=(*sp)["ME_wgtinfo"];
    if (seinfo) wgtinfo=seinfo->Get<ME_wgtinfo*>();
   
    Blob_Data_Base * bdb((*sp)["NLO_subeventlist"]);
    if (bdb) subevtlist=bdb->Get<NLO_subevtlist*>();
  }
  for (ATOOLS::Blob_List::iterator blit=blobs->begin();
       blit!=blobs->end();++blit) {
    Blob* blob=*blit;
    for (int i=0;i<blob->NInP();i++) {
      if (blob->InParticle(i)->ProductionBlob()==NULL) {
        Particle* parton=blob->InParticle(i);
        ATOOLS::Vec4D mom  = parton->Momentum();
        HepMC::FourVector momentum(mom[1],mom[2],mom[3],mom[0]);
        HepMC::GenParticle* inpart = 
	  new HepMC::GenParticle(momentum,parton->Flav().HepEvt(),2);
        vertex->add_particle_in(inpart);
        // distinct because SHRIMPS has no bunches for some reason
        if (blob->Type()==btp::Beam || blob->Type()==btp::Bunch) {
          beamparticles.push_back(inpart);
          beamparts.push_back(std::make_pair(momentum,parton->Flav().HepEvt()));
        }
      }
    }
    for (int i=0;i<blob->NOutP();i++) {
      if (blob->OutParticle(i)->DecayBlob()==NULL) {
        Particle* parton=blob->OutParticle(i);
        ATOOLS::Vec4D mom  = parton->Momentum();
        HepMC::FourVector momentum(mom[1],mom[2],mom[3],mom[0]);
        HepMC::GenParticle* outpart = 
	  new HepMC::GenParticle(momentum,parton->Flav().HepEvt(),1);
        vertex->add_particle_out(outpart);
        if (blob->Type()==btp::Beam) {
          if      (mom[3]>0) 
	    remnantparts1.push_back(std::make_pair(momentum,
						   parton->Flav().HepEvt()));
          else if (mom[3]<0) 
	    remnantparts2.push_back(std::make_pair(momentum,
						   parton->Flav().HepEvt()));
          else THROW(fatal_error,"Ill defined beam remnants.");
        }
      }
    }
    
    if ((*blit)->Type()==ATOOLS::btp::Signal_Process) {
      if((*blit)->NInP()==2) {
        kf_code fl1=(*blit)->InParticle(0)->Flav().HepEvt();
        kf_code fl2=(*blit)->InParticle(1)->Flav().HepEvt();
        double x1=(*blit)->InParticle(0)->Momentum()[0]/rpa->gen.PBeam(0)[0];
        double x2=(*blit)->InParticle(1)->Momentum()[0]/rpa->gen.PBeam(1)[0];
        double q(0.0), p1(0.0), p2(0.0);
        Blob_Data_Base *facscale((**blit)["Factorisation_Scale"]);
        if (facscale) q=sqrt(facscale->Get<double>());
	Blob_Data_Base *xf1((**blit)["XF1"]);
        Blob_Data_Base *xf2((**blit)["XF2"]);
        if (xf1) p1=xf1->Get<double>();
        if (xf2) p2=xf2->Get<double>();
	HepMC::PdfInfo pdfinfo(fl1, fl2, x1, x2, q, p1, p2);
	event.set_pdf_info(pdfinfo);
      }
    }
  }
  event.add_vertex(vertex);
  if (beamparticles.size()==2) {
    event.set_beam_particles(beamparticles[0],beamparticles[1]);
  }
  std::vector<double> weights; weights.push_back(weight);
  if (sp && !subevtlist) {
    Blob_Data_Base *info;
    info=((*sp)["MEWeight"]);
    if (!info) THROW(fatal_error,"Missing weight info.");
    double meweight(info->Get<double>());
    weights.push_back(meweight);
    info=((*sp)["Weight_Norm"]);
    if (!info) THROW(fatal_error,"Missing weight normalisation.");
    double weightnorm(info->Get<double>());
    weights.push_back(weightnorm);
    info=(*sp)["Trials"];
    if (!info) THROW(fatal_error,"Missing nof trials.");
    double trials(info->Get<double>());
    weights.push_back(trials);
    //alphaS value && power
    double rscale2 = (*sp)["Renormalization_Scale"]->Get<double>();
    double alphaS = MODEL::s_model->ScalarFunction("alpha_S",rscale2);
    event.set_alphaQCD(alphaS);
    double aSpower = ((*sp)["OQCD"])->Get<int>();
    weights.push_back(aSpower);
    
    if (wgtinfo) {
      //dump weight_0
      weights.push_back(wgtinfo->m_w0);
      //dump number of usr weights
      weights.push_back(wgtinfo->m_nx);
      //store xprimes
      weights.push_back(wgtinfo->m_y1);
      weights.push_back(wgtinfo->m_y2);
      //fill in usr weights
      for (int i=0;i<wgtinfo->m_nx;i++) {
	weights.push_back(wgtinfo->p_wx[i]);
      }
    }
  }
  
  event.weights()=weights;

  if (subevtlist) {
    // build GenEvent for all subevts (where only the signal is available)
    // use stored beam & remnant particles from above
    // sub->m_flip==1 -> momenta need to be inverted for analyses
    for (size_t i(0);i<subevtlist->size();++i) {
      NLO_subevt * sub((*subevtlist)[i]);
      if (sub->m_result==0.) continue;
      HepMC::GenVertex * subvertex(new HepMC::GenVertex());
      HepMC::GenEvent * subevent(new HepMC::GenEvent());
      // assume that only 2->(n-2) processes
      HepMC::GenParticle *beam[2];
      if (beamparts.size()==2) {
        for (size_t j(0);j<beamparts.size();++j) {
          beam[j] = new HepMC::GenParticle(beamparts[j].first,
                                           beamparts[j].second,2);
          subvertex->add_particle_in(beam[j]);
        }
      }
      else {
        const ATOOLS::Vec4D *mom(sub->p_mom);
        const ATOOLS::Flavour *fl(sub->p_fl);
        for (size_t j(0);j<2;++j) {
          HepMC::FourVector momentum;
          momentum.set( mom[j][1], mom[j][2], mom[j][3],mom[j][0]);
          ATOOLS::Flavour flc(fl[j]);
          HepMC::GenParticle* inpart
              = new HepMC::GenParticle(momentum,flc.HepEvt(),2);
          subvertex->add_particle_in(inpart);
        }
      }
      const ATOOLS::Vec4D *mom(sub->p_mom);
      const ATOOLS::Flavour *fl(sub->p_fl);
      for (size_t j(2);j<(*subevtlist)[i]->m_n;++j) {
        HepMC::FourVector momentum;
	momentum.set( mom[j][1], mom[j][2], mom[j][3],mom[j][0]);
        ATOOLS::Flavour flc(fl[j]);
        HepMC::GenParticle* outpart
            = new HepMC::GenParticle(momentum,flc.HepEvt(),1);
        subvertex->add_particle_out(outpart);
      }
      // if beamremnants are present:
      // scale beam remnants of real event for energy momentum conservation :
      //   flavours might not add up properly for sub events,
      //   but who cares. they go down the beam pipe.
      // also assume they are all massless :
      //   this will give momentum conservation violations
      //   which are collider dependent only
      //
      //   for real event (as constructed in BRH) :
      //
      //     P = p + \sum r_i  with  P^2 = m^2  and  r_i^2 = p^2 = 0
      //
      //     further  P  = ( P^0 , 0 , 0 , P^z )
      //              p  = (  p  , 0 , 0 ,  p  )
      //             r_i = ( r_i , 0 , 0 , r_i )
      //
      //     => P^0 = p + \sum r_i
      //        P^z = \sqrt{(P^0)^2 - m^2} <  p + \sum r_i
      //
      // in a mass-symmetric collider, the excess is the same for both beams
      // ensuring momentum conservation
      //
      //   for sub event (constructed here):
      //
      //     P = p~ + \sum r_i~ = p~ + \sum u*r_i
      //
      //     where u = ( P^0 - p^0~ ) / \sum r_i^0
      //
      //     again, the r_i~ = u*r_i are constructed such that
      //
      //     => P^0 = p~ + \sum u*r_i
      //        P^z = \sqrt{(P^0)^2 - m^2} <  p~ + \sum u*r_i =  p + \sum r_i
      //
      //     leading to the same momentum conservation violations per beam
      //
      if (remnantparts1.size()!=0 && remnantparts2.size()!=0) {
        double res1(0.),res2(0.);
        for (size_t j(0);j<remnantparts1.size();++j) {
          res1+=remnantparts1[j].first.e();
        }
        for (size_t j(0);j<remnantparts2.size();++j) {
          res2+=remnantparts2[j].first.e();
        }
        ATOOLS::Vec4D hardparton[2];
        for (size_t j(0);j<2;++j) {
	  hardparton[j]=ATOOLS::Vec4D(mom[j][0],Vec3D( mom[j]));
        }
        // incoming partons might need to be flipped due to particle sorting
        bool flip(hardparton[0][3]<0);
        double u1((beamparts[0].first.e()-hardparton[flip?1:0][0])/res1);
        double u2((beamparts[1].first.e()-hardparton[flip?0:1][0])/res2);
        // filling
        for (size_t j(0);j<remnantparts1.size();++j) {
          HepMC::FourVector momentum(u1*remnantparts1[j].first.px(),
                                     u1*remnantparts1[j].first.py(),
                                     u1*remnantparts1[j].first.pz(),
                                     u1*remnantparts1[j].first.e());
          HepMC::GenParticle* outpart
              = new HepMC::GenParticle(momentum,remnantparts1[j].second,1);
          subvertex->add_particle_out(outpart);
        }
        for (size_t j(0);j<remnantparts2.size();++j) {
          HepMC::FourVector momentum(u2*remnantparts2[j].first.px(),
                                     u2*remnantparts2[j].first.py(),
                                     u2*remnantparts2[j].first.pz(),
                                     u2*remnantparts2[j].first.e());
          HepMC::GenParticle* outpart
              = new HepMC::GenParticle(momentum,remnantparts2[j].second,1);
          subvertex->add_particle_out(outpart);
        }
        if (beamparticles.size()==2) {
          subevent->set_beam_particles(beam[0],beam[1]);
        }
      }
      subevent->add_vertex(subvertex);
      // not enough info in subevents to set PDFInfo properly,
      // so set only flavours, x1, x2, and q from the Signal_Process
      HepMC::PdfInfo subpdfinfo(*event.pdf_info());
      double q = sqrt(sub->m_mu2[stp::fac]);
      if (q!=0. && q != subpdfinfo.scalePDF()) 
        subpdfinfo.set_scalePDF(q);
      if (sub->m_xf1) subpdfinfo.set_pdf1(sub->m_xf1);
      if (sub->m_xf2) subpdfinfo.set_pdf2(sub->m_xf2);
      subevent->set_pdf_info(subpdfinfo);
      // add weight
      std::vector<double> subweight; subweight.push_back(sub->m_result);
      Blob_Data_Base *info;
      info=((*sp)["MEWeight"]);
      if (!info) THROW(fatal_error,"Missing weight info.");
      double meweight(info->Get<double>());
      subweight.push_back(meweight);
      info=((*sp)["Weight_Norm"]);
      if (!info) THROW(fatal_error,"Missing weight normalisation.");
      double weightnorm(info->Get<double>());
      subweight.push_back(weightnorm);
      info=(*sp)["Trials"];
      if (!info) THROW(fatal_error,"Missing nof trials.");
      double trials(info->Get<double>());
      subweight.push_back(trials);
      //alphaS value && power
      double alphaS = MODEL::s_model->ScalarFunction("alpha_S",sub->m_mu2[stp::ren]);
      subevent->set_alphaQCD(alphaS);
      double aSpower = ((*sp)["OQCD"])->Get<int>();
      subweight.push_back(aSpower);
      subweight.push_back(sub->m_mewgt);
      
      if (wgtinfo) {
	//dump number of usr weights
	subweight.push_back(wgtinfo->m_nx);
	//store xprimes
	subweight.push_back(wgtinfo->m_y1);
	subweight.push_back(wgtinfo->m_y2);
	//fill in usr weights
	for (int i=0;i<wgtinfo->m_nx;i++) {
	  subweight.push_back(wgtinfo->p_wx[i]);
	}
      }
      //
      subevent->weights()=subweight;
      // set the event number (could be used to identify correlated events)
      subevent->set_event_number(ATOOLS::rpa->gen.NumberOfGeneratedEvents());
      m_subeventlist.push_back(subevent);
    }
  }
  return true;
}