Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-03 08:20:01

0001 /*******************************************************************************
0002  * Copyright (c) The JETSCAPE Collaboration, 2019
0003  *
0004  * Modular, task-based framework for simulating all aspects of heavy-ion collisions
0005  *
0006  * For the list of contributors see AUTHORS.
0007  *
0008  * Report issues at https://github.com/JETSCAPE/JETSCAPE/issues
0009  *
0010  * or via email to bugs.jetscape@gmail.com
0011  *
0012  * Distributed under the GNU General Public License 3.0 (GPLv3 or later).
0013  * See COPYING for details.
0014  ******************************************************************************/
0015 
0016 #include "HybridHadronization.h"
0017 #include "ThermPtnSampler.h"
0018 #include "JetScapeXML.h"
0019 #include "JetScapeLogger.h"
0020 #include "tinyxml2.h"
0021 #include "JetScapeConstants.h"
0022 
0023 #include "FluidDynamics.h"
0024 #include "FluidCellInfo.h"
0025 #include "SurfaceCellInfo.h"
0026 #include "FluidEvolutionHistory.h"
0027 #include "JetScapeSignalManager.h"
0028 
0029 #include <sstream>
0030 #include <iostream>
0031 #include <fstream>
0032 #include <sstream>
0033 #include <random>
0034 #include <algorithm>
0035 #include <limits>
0036 //#include <cmath>
0037 
0038 using namespace Jetscape;
0039 using namespace Pythia8;
0040 
0041 // Register the module with the base class
0042 RegisterJetScapeModule<HybridHadronization> HybridHadronization::reg("HybridHadronization");
0043 
0044 // Initialize static helper here
0045 Pythia8::Pythia HybridHadronization::pythia ("IntentionallyEmpty",false);
0046 
0047 //RNG - Mersenne Twist - 64 bit
0048 //std::mt19937_64 eng(std::random_device{}());
0049 //std::mt19937_64 eng(1);
0050 //returns a random number between 0 and 1, based on above engine
0051 double HybridHadronization::ran() {
0052   std::uniform_real_distribution<double> uniran(0.0,1.0);
0053   return uniran(eng);
0054 }
0055 
0056 HybridHadronization::HybridHadronization(){
0057   SetId("HybridHadronization");
0058   VERBOSE(8);
0059 }
0060 
0061 HybridHadronization::~HybridHadronization(){
0062   VERBOSE(8);
0063 }
0064 
0065 //meson width function
0066 double HybridHadronization::SigM2_calc(double R2chg, double qm1, double qm2, double qq1, double qq2){
0067   return R2chg*(2./3.)*(qm1+qm2)*(qm1+qm2)/(std::abs(qq1)*qm2*qm2 + std::abs(qq2)*qm1*qm1) * (std::abs(qq1) + std::abs(qq2));
0068 }
0069 
0070 //baryon width function
0071 double HybridHadronization::SigBR2_calc(double R2chg, double qm1, double qm2, double qm3, double qq1, double qq2, double qq3){
0072     return R2chg*(2./3.)*(qm1+qm2+qm3)/(std::abs(qq1)*qm2*(qm2+qm3)/(qm1+qm2)+std::abs(qq2)*qm1*(qm1+qm3)/(qm1+qm2)+std::abs(qq3)*(qm1*qm2)/qm3) * (std::abs(qq1) + std::abs(qq2) + std::abs(qq3));
0073 }
0074 
0075 double HybridHadronization::SigBL2_calc(double SigBR2, double qm1, double qm2, double qm3){
0076   return SigBR2*((qm1*qm2)/(qm1+qm2))/(qm3*(qm1+qm2)/(qm1+qm2+qm3));
0077 }
0078 
0079 void HybridHadronization::Init(){
0080 
0081   tinyxml2::XMLElement *hadronization = GetXMLElement({"JetHadronization"});
0082 
0083   if ( !hadronization ) {
0084     JSWARN << "Couldn't find tag Jet Hadronization";
0085     throw std::runtime_error ("Couldn't find tag Jet Hadronization");
0086   }
0087   if (hadronization) {
0088     string s = hadronization->FirstChildElement( "name" )->GetText();
0089       //std::string s = GetXMLElementText({"JetHadronization", "name"});
0090       JSDEBUG << s << " to be initialized ...";
0091       JSINFO<<"Initialize Hybrid Hadronization ...";
0092 
0093     JSDEBUG<<"Initialize HybridHadronization";
0094     VERBOSE(8);
0095 
0096     maxM_level    = 1;      //maximum energy level considered for meson recombination; maximum: 4
0097     maxB_level    = 1;    //maximum energy level considered for baryon recombination; no maximum but no physical baryons beyond 0
0098     goldstonereco = false; // don't allow recombination of Goldstone bosons
0099       gmax          = 1.25;     //maximum allowed mass of the gluon (for q-qbar split), in GeV
0100       xmq           = 0.33; //light quark mass, in GeV
0101       xms           = 0.5;  //strange quark mass, in GeV
0102     xmc           = 1.5;  //charm quark mass in GeV
0103     xmb           = 4.8;  //bottom quark mass in GeV
0104       hbarc         = 0.197327; // GeV*fm - maybe just set this as a constant in common?
0105       dist2cut      = 25.;      //maximum distance [fm] squared for recombination (involving thermal partons) - in lab frame
0106       sh_recofactor = 1.;       //suppression/enhancement factor for shower-shower recombination
0107       th_recofactor = 1.;       //suppression/enhancement factor for shower-thermal recombination
0108       attempts_max  = 15;       //maximum number of failed attempts to hadronize a single event before we give up.
0109       p_fake        = 0.;       //momentum used for fake parton, if needed
0110       rand_seed     = 0;        //seed for RNGs used - 0 means use a randomly determined random seed (from system time or std::random_device{}())
0111       had_prop      = 0.;       //propagation of hadrons after formation by this time in lab frame
0112     part_prop     = 0.;   //minimum propagation time of partons after last split
0113     reco_hadrons_pythia = 0; //flag to put recombination hadrons into pythia for decays (position would be lost)
0114 
0115       //xml read in to alter settings...
0116       double xml_doublein = -1.; int xml_intin = -1; unsigned int xml_uintin = std::numeric_limits<unsigned int>::max();
0117 
0118       xml_doublein = GetXMLElementDouble({"JetHadronization", "eCMforHadronization"});
0119       if(xml_doublein >= 0.){p_fake = xml_doublein / 6.;} xml_doublein = -1.; // for colliders set fake momentum to valence quark energy
0120 
0121       xml_doublein = GetXMLElementDouble({"JetHadronization", "thermreco_distmax"});
0122       if(xml_doublein >= 0.){dist2cut = xml_doublein*xml_doublein;} xml_doublein = -1.;
0123 
0124       xml_doublein = GetXMLElementDouble({"JetHadronization", "shower_recofactor"});
0125       if(xml_doublein >= 0.){sh_recofactor = xml_doublein;} xml_doublein = -1.;
0126 
0127       xml_doublein = GetXMLElementDouble({"JetHadronization", "thermal_recofactor"});
0128       if(xml_doublein >= 0.){th_recofactor = xml_doublein;} xml_doublein = -1.;
0129 
0130     xml_intin = GetXMLElementInt({"JetHadronization", "reco_Mlevelmax"});
0131       if(xml_intin >= 0){maxM_level = xml_intin;} xml_intin = -1;
0132 
0133     xml_intin = GetXMLElementInt({"JetHadronization", "reco_Blevelmax"});
0134       if(xml_intin >= -1){maxB_level = xml_intin;} xml_intin = -1;
0135 
0136     xml_intin = GetXMLElementInt({"JetHadronization", "reco_goldstone"});
0137       if(xml_intin >= 0){goldstonereco = xml_intin;} xml_intin = -1;
0138 
0139     torder_reco = false;
0140       xml_intin = GetXMLElementInt({"JetHadronization", "recobias_t"});
0141       if(xml_intin == 1){torder_reco = true;} xml_intin = -1;
0142 
0143     xml_doublein = GetXMLElementDouble({"JetHadronization", "hydro_Tc"});
0144       if(xml_doublein >= 0){hydro_Tc = xml_doublein;} xml_doublein = -1;
0145 
0146     xml_doublein = GetXMLElementDouble({"JetHadronization", "had_postprop"});
0147       if(xml_doublein >= 0){had_prop = xml_doublein;} xml_doublein = -1;
0148 
0149     xml_doublein = GetXMLElementDouble({"JetHadronization", "part_prop"});
0150       if(xml_doublein >= 0){part_prop = xml_doublein;} xml_doublein = -1;
0151 
0152       xml_intin = GetXMLElementInt({"JetHadronization", "reco_hadrons_in_pythia"});
0153       if(xml_intin == 0 || xml_intin == 1){reco_hadrons_pythia = xml_intin;} xml_intin = -1;
0154 
0155     xml_intin = GetXMLElementInt({"Afterburner", "include_fragmentation_hadrons"});
0156       if(xml_intin == 1){afterburner_frag_hadrons = true;} xml_intin = -1;
0157 
0158     if(maxM_level > 4) {
0159       maxM_level=4;
0160       JSWARN << "Requested maximum energy level for mesons too large. Set it to 4.";
0161     }
0162     // No, really, the maximum is four
0163 
0164       // random seed
0165       // xml limits us to unsigned int :-/ -- but so does 32 bits Mersenne Twist
0166       tinyxml2::XMLElement *RandomXmlDescription = GetXMLElement({"Random"});
0167       if ( RandomXmlDescription ){
0168           tinyxml2::XMLElement *xmle; xmle = RandomXmlDescription->FirstChildElement( "seed" );
0169           xmle->QueryUnsignedText(&xml_uintin);
0170           if(xml_uintin < std::numeric_limits<unsigned int>::max()){rand_seed = xml_uintin;} xml_uintin = std::numeric_limits<unsigned int>::max();
0171       }else{
0172           JSWARN << "No <Random> element found in xml, seeding to 0";
0173       }
0174       VERBOSE(7) <<"Seeding PYTHIA(hadronization) to "<< rand_seed;
0175 
0176       //not sure if we can seed with a negative integer...
0177       if(rand_seed != 0){eng.seed(rand_seed);}
0178       //else{eng.seed(std::random_device{}());}
0179       else{ //seeding the mt19937_64 object 'eng' PROPERLY!
0180           std::random_device rd;
0181           std::array<int,std::mt19937_64::state_size> seedarray; std::generate_n(seedarray.data(), seedarray.size(), std::ref(rd));
0182           std::seed_seq seeds(std::begin(seedarray), std::end(seedarray)); eng.seed(seeds);
0183       }
0184 
0185 
0186       //Since PYTHIA has no spacetime information, we shouldn't use recombination as it is necessary to calculate recombination probabilities
0187       //later, this will instead update to set a flag to attempt to artificially generate this information
0188       //for now, we just print a warning - but still try to run recombination.  It will just be unphysically enhanced, esp. for certain configurations
0189       //tinyxml2::XMLElement *XmlPythiaGun=JetScapeXML::Instance()->GetXMLRoot()->FirstChildElement("Hard" )->FirstChildElement("PythiaGun");
0190     /*  tinyxml2::XMLElement *XmlPythiaGun = GetXMLElement({"Hard", "PythiaGun"});
0191       bool PYgun_FSRon = false;
0192       if ( XmlPythiaGun ){
0193           tinyxml2::XMLElement *xmle; xmle = XmlPythiaGun->FirstChildElement( "FSR_on" );
0194           xmle->QueryIntText(&xml_intin);
0195           if(xml_intin == 1){PYgun_FSRon = true;} xml_intin = -1;
0196       }
0197       if(PYgun_FSRon && (sh_recofactor > 0.0000000001)){JSWARN << "Recombination with a PYTHIA FSR shower is not fully implemented.";}
0198     */
0199       xml_intin = GetXMLElementInt({"Hard", "PythiaGun", "FSR_on"});
0200       if(xml_intin && (sh_recofactor > 0.0000000001)){JSWARN << "Recombination with a PYTHIA FSR shower is not fully implemented.";}
0201       xml_intin = -1;
0202 
0203       //quark masses/charges used to get widths from charged radii (use Pythia masses)
0204       double Qm_ud = xmq; double Qm_s = xms; double Qm_c = xmc; double Qm_b = xmb;
0205       double chg_u = 2./3.; double chg_d = -1./3.;
0206 
0207       //rms charge radii
0208       //mesons
0209       double R2chg_Pi  = 0.42 ;
0210       double R2chg_Phi = 0.21 ;
0211       double R2chg_K   = 0.34 ;
0212       double R2chg_Jpi = 0.04 ;
0213       double R2chg_Ds  = 0.09 ;
0214       double R2chg_D   = 0.165;
0215       double R2chg_Ups = 0.032; //????? setting to a linear extrapolation from Jpsi -> Bc -> Ups
0216       double R2chg_Bc  = 0.036;
0217       double R2chg_B   = 0.273;
0218       //baryons
0219       double R2chg_Nuc  = 0.69 ;
0220       double R2chg_Omg  = 0.355;
0221       double R2chg_Xi   = 0.52 ;
0222       double R2chg_Sig  = 0.61 ;
0223       double R2chg_Occc = 0.179; //?????
0224       double R2chg_Occ  = 0.043; //?
0225       double R2chg_Xicc = 0.049; //?
0226       double R2chg_Oc   = 0.1  ; //?????
0227       double R2chg_Xic  = 0.24 ; //?
0228       double R2chg_Sigc = 0.27 ; //?
0229       double R2chg_Obbb = 0.001; //?????
0230       double R2chg_Obbc = 0.001; //?????
0231       double R2chg_Obb  = 0.001; //?????
0232       double R2chg_Xibb = 0.001; //?????
0233       double R2chg_Obcc = 0.001; //?????
0234       double R2chg_Obc  = 0.001; //?????
0235       double R2chg_Xibc = 0.001; //?????
0236       double R2chg_Ob   = 0.6  ; //?????
0237       double R2chg_Xib  = 0.63 ; //?????
0238       double R2chg_Sigb = 0.66 ; //?????
0239 
0240       //meson width calculations (r2) - recalc if r2chg is changed on command line...
0241       SigPi2  = SigM2_calc(R2chg_Pi,  Qm_ud, Qm_ud, chg_d, chg_u);
0242       SigPhi2 = SigM2_calc(R2chg_Phi, Qm_s,  Qm_s,  chg_d, -chg_d); //normalizing
0243       SigK2   = SigM2_calc(R2chg_K,   Qm_s,  Qm_ud, chg_d, chg_u);
0244       SigJpi2 = SigM2_calc(R2chg_Jpi, Qm_c,  Qm_c,  chg_u, -chg_u); //normalizing
0245       SigDs2  = SigM2_calc(R2chg_Ds,  Qm_c,  Qm_s,  chg_u, chg_d);
0246       SigD2   = SigM2_calc(R2chg_D,   Qm_c,  Qm_ud, chg_u, chg_d);
0247       SigUps2 = SigM2_calc(R2chg_Ups, Qm_b,  Qm_b,  chg_d, -chg_d); //normalizing
0248       SigBc2  = SigM2_calc(R2chg_Bc,  Qm_b,  Qm_c,  chg_d, chg_u);
0249       SigB2   = SigM2_calc(R2chg_B,   Qm_b,  Qm_ud, chg_d, chg_u); // (treating B_s as B)
0250 
0251       //baryon width calculations (r2) - recalc if r2chg is changed on command line...
0252       //light/strange baryons
0253       SigNucR2 = SigBR2_calc(R2chg_Nuc, Qm_ud, Qm_ud, Qm_ud, chg_d, chg_u, chg_u);
0254       SigNucL2 = SigBL2_calc(SigNucR2,  Qm_ud, Qm_ud, Qm_ud);
0255       SigOmgR2 = SigBR2_calc(R2chg_Omg, Qm_s,  Qm_s,  Qm_s,  chg_d, chg_d, chg_d);
0256       SigOmgL2 = SigBL2_calc(SigOmgR2,  Qm_s,  Qm_s,  Qm_s );
0257       SigXiR2  = SigBR2_calc(R2chg_Xi,  Qm_s,  Qm_s,  Qm_ud, chg_d, chg_d, chg_d);
0258       SigXiL2  = SigBL2_calc(SigXiR2,   Qm_s,  Qm_s,  Qm_ud);
0259       SigSigR2 = SigBR2_calc(R2chg_Sig, Qm_s,  Qm_ud, Qm_ud, chg_d, chg_u, chg_u);
0260       SigSigL2 = SigBL2_calc(SigSigR2,  Qm_s,  Qm_ud, Qm_ud);
0261 
0262       //charm baryons
0263       SigOcccR2 = SigBR2_calc(R2chg_Occc, Qm_c, Qm_c,  Qm_c,  chg_d, chg_d, chg_d); // ! maybe need to normalize? (just setting all to -1/3 for now)
0264       SigOcccL2 = SigBL2_calc(SigOcccR2,  Qm_c, Qm_c,  Qm_c );
0265       SigOccR2  = SigBR2_calc(R2chg_Occ,  Qm_c, Qm_c,  Qm_s,  chg_u, chg_u, chg_d);
0266       SigOccL2  = SigBL2_calc(SigOccR2,   Qm_c, Qm_c,  Qm_s );
0267       SigXiccR2 = SigBR2_calc(R2chg_Xicc, Qm_c, Qm_c,  Qm_ud, chg_u, chg_u, chg_d);
0268       SigXiccL2 = SigBL2_calc(SigXiccR2,  Qm_c, Qm_c,  Qm_ud);
0269       SigOcR2   = SigBR2_calc(R2chg_Oc,   Qm_c, Qm_s,  Qm_s,  chg_d, chg_d, chg_d); // ! setting all quark charges to -1/3
0270       SigOcL2   = SigBL2_calc(SigOcR2,    Qm_c, Qm_s,  Qm_s );
0271       SigXicR2  = SigBR2_calc(R2chg_Xic,  Qm_c, Qm_s,  Qm_ud, chg_u, chg_d, chg_u);
0272       SigXicL2  = SigBL2_calc(SigXicR2,   Qm_c, Qm_s,  Qm_ud);
0273       SigSigcR2 = SigBR2_calc(R2chg_Sigc, Qm_c, Qm_ud, Qm_ud, chg_u, chg_d, chg_u);
0274       SigSigcL2 = SigBL2_calc(SigSigcR2,  Qm_c, Qm_ud, Qm_ud);
0275 
0276       //bottom baryons
0277       SigObbbR2 = SigBR2_calc(R2chg_Obbb, Qm_b, Qm_b,  Qm_b,  chg_d, chg_d, chg_d);
0278       SigObbbL2 = SigBL2_calc(SigObbbR2,  Qm_b, Qm_b,  Qm_b );
0279       SigObbcR2 = SigBR2_calc(R2chg_Obbc, Qm_b, Qm_b,  Qm_c,  chg_d, chg_d, chg_d); // ! setting all quark charges to -1/3
0280       SigObbcL2 = SigBL2_calc(SigObbcR2,  Qm_b, Qm_b,  Qm_c );
0281       SigObbR2  = SigBR2_calc(R2chg_Obb,  Qm_b, Qm_b,  Qm_s,  chg_d, chg_d, chg_d);
0282       SigObbL2  = SigBL2_calc(SigObbR2,   Qm_b, Qm_b,  Qm_s );
0283       SigXibbR2 = SigBR2_calc(R2chg_Xibb, Qm_b, Qm_b,  Qm_ud, chg_d, chg_d, chg_d);
0284       SigXibbL2 = SigBL2_calc(SigXibbR2,  Qm_b, Qm_b,  Qm_ud);
0285       SigObccR2 = SigBR2_calc(R2chg_Obcc, Qm_b, Qm_c,  Qm_c,  chg_d, chg_u, chg_u);
0286       SigObccL2 = SigBL2_calc(SigObccR2,  Qm_b, Qm_c,  Qm_c );
0287       SigObcR2  = SigBR2_calc(R2chg_Obc,  Qm_b, Qm_c,  Qm_s,  chg_d, chg_d, chg_d); // ! flipping c quark charge (all to -1/3)
0288       SigObcL2  = SigBL2_calc(SigObcR2,   Qm_b, Qm_c,  Qm_s );
0289       SigXibcR2 = SigBR2_calc(R2chg_Xibc, Qm_b, Qm_c,  Qm_ud, chg_d, chg_u, chg_u);
0290       SigXibcL2 = SigBL2_calc(SigXibcR2,  Qm_b, Qm_c,  Qm_ud);
0291       SigObR2   = SigBR2_calc(R2chg_Ob,   Qm_b, Qm_s,  Qm_s,  chg_d, chg_d, chg_d);
0292       SigObL2   = SigBL2_calc(SigObR2,    Qm_b, Qm_s,  Qm_s );
0293       SigXibR2  = SigBR2_calc(R2chg_Xib,  Qm_b, Qm_s,  Qm_ud, chg_d, chg_d, chg_d);
0294       SigXibL2  = SigBL2_calc(SigXibR2,   Qm_b, Qm_s,  Qm_ud);
0295       SigSigbR2 = SigBR2_calc(R2chg_Sigb, Qm_b, Qm_ud, Qm_ud, chg_d, chg_u, chg_u);
0296       SigSigbL2 = SigBL2_calc(SigSigbR2,  Qm_b, Qm_ud, Qm_ud);
0297 
0298     // No event record printout.
0299     pythia.readString("Next:numberShowInfo = 0");
0300     pythia.readString("Next:numberShowProcess = 0");
0301     pythia.readString("Next:numberShowEvent = 0");
0302     pythia.readString("Init:showProcesses = off");
0303     pythia.readString("Init:showChangedSettings = off");
0304     pythia.readString("Init:showMultipartonInteractions = off");
0305     pythia.readString("Init:showChangedParticleData = off");
0306 
0307     // Standard settings
0308     pythia.readString("ProcessLevel:all = off");
0309       //pythia.readString("PartonLevel:FSR=off"); //is this necessary?
0310 
0311     // General settings for hadron decays
0312     pythia_decays = GetXMLElementText({"JetHadronization", "pythia_decays"});
0313     double tau0Max = 10.0;
0314     double tau0Max_xml = GetXMLElementDouble({"JetHadronization", "tau0Max"});
0315       if(tau0Max_xml >= 0){tau0Max = tau0Max_xml;}
0316     else{JSWARN << "tau0Max should be larger than 0. Set it to 10.";}
0317     if(pythia_decays == "on"){
0318       JSINFO << "Pythia decays are turned on for tau0Max < " << tau0Max;
0319       pythia.readString("HadronLevel:Decay = on");
0320       pythia.readString("ParticleDecays:limitTau0 = on");
0321       pythia.readString("ParticleDecays:tau0Max = " + std::to_string(tau0Max));
0322     } else {
0323       JSINFO << "Pythia decays are turned off";
0324       pythia.readString("HadronLevel:Decay = off");
0325     }
0326 
0327     // Settings for decays (old flag, will be depracted at some point)
0328     // This overwrites the previous settings if the user xml file contains the flag
0329     std::string weak_decays =
0330       GetXMLElementText({"JetHadronization", "weak_decays"});
0331     if (weak_decays == "off") {
0332       JSINFO << "Hadron decays are turned off.";
0333       JSWARN << "This parameter will be depracted at some point. Use 'pythia_decays' instead.\nOverwriting 'pythia_decays'.";
0334       pythia.readString("HadronLevel:Decay = off");
0335     } else if(weak_decays == "on") {
0336       JSINFO << "Hadron decays inside a range of 10 mm/c are turned on.";
0337       JSWARN << "This parameter will be depracted at some point. Use 'pythia_decays' and 'tau0Max' for more control on decays.\nOverwriting 'pythia_decays' and fix 'tau0Max' to 10.";
0338       pythia.readString("HadronLevel:Decay = on");
0339       pythia.readString("ParticleDecays:limitTau0 = on");
0340       pythia.readString("ParticleDecays:tau0Max = 10.0");
0341     }
0342 
0343       //setting seed, or using random seed
0344       pythia.readString("Random:setSeed = on");
0345       pythia.readString("Random:seed = " + std::to_string(rand_seed));
0346 
0347       //additional settings
0348       //turning off pythia checks for runtime decrease (can be turned back on if necessary, but it shouldn't make much of a difference)
0349       pythia.readString("Check:event = off");      // is probably a bad idea, but shouldn't really be necessary... will use a bit of runtime on event checks...
0350       pythia.readString("Check:history = off");    // might be a good idea to set 'off' as it saves runtime - provided we know that we've set up mother/daughter relations correctly...
0351 
0352       //making the pythia event checks a little less stringent (PYTHIA documentation already states that LHC events will occasionally violate default constraint, without concern)
0353       //pythia.readString("Check:epTolWarn = 1e-4");   // setting E/P conservation violation constraint somewhat weaker, just for ease
0354       //pythia.readString("Check:epTolErr  = 1e-2");   // setting E/P conservation violation constraint somewhat weaker, just for ease
0355       //pythia.readString("Check:mTolWarn  = 1e-2");   // setting EP/M conservation violation constraint somewhat weaker, just for ease
0356       //pythia.readString("Check:mTolErr   = 1e-1");   // setting EP/M conservation violation constraint somewhat weaker, just for ease
0357 
0358       //allowing for partonic space-time information to be used by PYTHIA
0359       //pythia.readString("PartonVertex:setVertex = on");        //this might allow PYTHIA to keep track of partonic space-time information (default was for 'rope hadronization')
0360 
0361       //setting hadron color tags so that spacetime information can be reconstructed
0362       pythia.readString("StringFragmentation:TraceColours = on");
0363 
0364       //using QCD based color reconnection (original PYTHIA MPI based CR can't be used at hadron level)
0365       pythia.readString("ColourReconnection:reconnect = off");          //allowing color reconnections (should have been default on, but doing it here for clarity)
0366     /*pythia.readString("ColourReconnection:mode = 1");                //sets the color reconnection scheme to 'new' QCD based scheme (TODO: make sure this is better than (2)gluon move)
0367       pythia.readString("ColourReconnection:forceHadronLevelCR = on");  //allowing color reconnections for these constructed strings!
0368                                                                         //a few params for the QCD based color reconnection scheme are set below.
0369       pythia.readString("MultipartonInteractions:pT0Ref = 2.15");       //not sure if this is needed for this setup, but is part of the recommended 'default'
0370       pythia.readString("ColourReconnection:allowDoubleJunRem = off");  //default on - allows directly connected double junction systems to split into two strings
0371       pythia.readString("ColourReconnection:junctionCorrection = 1.15");
0372       pythia.readString("ColourReconnection:timeDilationMode = 3");     //allow reconnection if single pair of dipoles are in causal contact (maybe try 5 as well?)
0373       pythia.readString("ColourReconnection:timeDilationPar = 0.18");   //parameter used in causal interaction between strings (mode set above)(maybe try 0.073?)
0374     */
0375 
0376     std::stringstream lines;
0377     lines << GetXMLElementText({"JetHadronization", "LinesToRead"}, false);
0378     while (std::getline(lines, s, '\n')) {
0379       if (s.find_first_not_of(" \t\v\f\r") == s.npos)
0380         continue; // skip empty lines
0381       JSINFO << "Also reading in: " << s;
0382       pythia.readString(s);
0383     }
0384 
0385     // optional input of another pythia particle data xml file (higher excited states,...)
0386     xml_intin = GetXMLElementInt({"JetHadronization", "additional_pythia_particles"});
0387       if(xml_intin == 0 || xml_intin == 1){additional_pythia_particles = xml_intin;} xml_intin = -1;
0388 
0389     if(additional_pythia_particles == 1) {
0390       std::string additional_pythia_particle_file =
0391         GetXMLElementText({"JetHadronization", "additional_pythia_particles_path"});
0392       pythia.particleData.readXML(additional_pythia_particle_file,false);
0393     }
0394 
0395     // And initialize
0396     pythia.init();
0397 
0398     //reading in info for thermal partons
0399       inbrick = false; brickL = -1.;
0400     inhydro = false; nreusehydro = 1;
0401 
0402       xml_intin = GetXMLElementInt({"Eloss", "Matter", "brick_med"});
0403       if(xml_intin == 1){inbrick = true;} xml_intin = -1;
0404       xml_doublein = GetXMLElementDouble({"Eloss", "Matter", "brick_length"});
0405       if(inbrick && (xml_doublein >= 0.)){brickL = xml_doublein;} xml_doublein = -1.;
0406     xml_intin = GetXMLElementInt({"nReuseHydro"});
0407       if(xml_intin > 0){nreusehydro = xml_intin;} xml_intin = -1;
0408       xml_doublein = GetXMLElementDouble({"Eloss", "deltaT"});
0409       if(xml_doublein >= 0.){delta_t = xml_doublein;} xml_doublein = -1.;
0410 
0411     // Check if hydro is used in user xml file
0412     tinyxml2::XMLElement *elementXML = (tinyxml2::XMLElement *)JetScapeXML::Instance()->GetXMLRootUser()->FirstChildElement();
0413     while (elementXML) {
0414       std::string elementName = elementXML->Name();
0415       if (elementName == "Hydro") {
0416         inhydro = true;
0417       }
0418       elementXML = elementXML->NextSiblingElement();
0419     } // at this point the hydro could still be a brick -> check this in the following part
0420 
0421     if(inhydro){
0422       tinyxml2::XMLElement *element = (tinyxml2::XMLElement *)JetScapeXML::Instance()->GetXMLRootUser()->FirstChildElement();
0423       while (element) {
0424         std::string elementName = element->Name();
0425         if (elementName == "Hydro") {
0426           inhydro = true;
0427           tinyxml2::XMLElement *childElement = (tinyxml2::XMLElement *)element->FirstChildElement();
0428           while (childElement) {
0429             std::string childElementName = childElement->Name();
0430             if (childElementName == "Brick") {
0431               inbrick = true;
0432               inhydro = false;
0433             }
0434             childElement = childElement->NextSiblingElement();
0435           }
0436         }
0437         element = element->NextSiblingElement();
0438       }
0439     }
0440 
0441     // this is only important if a boost invariant 2+1d hydro is used
0442     xml_doublein = GetXMLElementDouble({"JetHadronization", "eta_max_boost_inv"});
0443       if(inhydro && (xml_doublein >= 0.)){eta_max_boost_inv = xml_doublein;} xml_doublein = -1.;
0444   }
0445 }
0446 
0447 void HybridHadronization::WriteTask(weak_ptr<JetScapeWriter> w){
0448   VERBOSE(8);
0449   auto f = w.lock();
0450   if ( !f ) return;
0451   f->WriteComment("Hadronization Module : "+GetId());
0452 }
0453 
0454 //TODO: Junction Strings, Thermal Partons
0455 void HybridHadronization::DoHadronization(vector<vector<shared_ptr<Parton>>>& shower, vector<shared_ptr<Hadron>>& hOut, vector<shared_ptr<Parton>>& pOut){
0456   number_p_fake = 0;    //reset counter for the number of fake partons
0457   double energy_hadrons = 0.; //needed for the kinetic scaling of the negative hadrons
0458 
0459   //JSINFO<<"Start Hybrid Hadronization using both Recombination and PYTHIA Lund string model.";
0460   pythia.event.reset(); HH_shower.clear();
0461   parton_collection neg_ptns;
0462 
0463   //pointer to get hydro temperature info
0464   std::unique_ptr<FluidCellInfo> check_fluid_info_ptr;
0465 
0466   bool boost_invariant = true;
0467   bool Cartesian_hydro = false; // not properly initialized by all hydro modules at the moment, don't use it
0468   if(inhydro){
0469       std::shared_ptr<FluidDynamics> hydro_ptr = JetScapeSignalManager::Instance()->GetHydroPointer().lock();
0470       const EvolutionHistory& bulk_info = hydro_ptr->get_bulk_info();
0471 
0472       boost_invariant = bulk_info.is_boost_invariant();
0473       Cartesian_hydro = bulk_info.is_Cartesian();
0474       Cartesian_hydro = false;
0475   }
0476 
0477   //negative brickL, then we will not run a brick sampler
0478     if(brickL < 0.){brickL = 0.; inbrick = false;}
0479 
0480   //The framework uses unsigned int for partons, while HHpartons have int anti-/color tags.
0481   //Changing the HH partons to unsigned int is not that easy as some workflow, e.g. in recomb(),
0482   //needs them to be integer in some structures. Let's have a workaround and set the
0483   //tags of partons which are too large for an int value to a new unused value.
0484   convert_color_tags_to_int_type(shower);
0485 
0486   double total_shower_energy = 0.; // used to scale the negative hadrons
0487   double total_shower_energy_neg = 0.; // used to scale the negative hadrons
0488   //sort positive partons into HH_shower and negative partons from LBT to neg_ptns
0489   for(unsigned int ishower=0; ishower < shower.size(); ++ishower){
0490       for(unsigned int ipart=0; ipart < shower.at(ishower).size(); ++ipart){
0491           HHparton sh_parton;
0492           sh_parton.is_shower(true); sh_parton.id(shower.at(ishower).at(ipart)->pid()); sh_parton.orig(0); //sh_parton.string_id(str)
0493           sh_parton.px(shower.at(ishower).at(ipart)->px()); sh_parton.py(shower.at(ishower).at(ipart)->py());
0494           sh_parton.pz(shower.at(ishower).at(ipart)->pz()); sh_parton.e(shower.at(ishower).at(ipart)->e());
0495           sh_parton.x( shower.at(ishower).at(ipart)->x_in().x() ); sh_parton.y( shower.at(ishower).at(ipart)->x_in().y() );
0496           sh_parton.z( shower.at(ishower).at(ipart)->x_in().z() ); sh_parton.x_t(shower.at(ishower).at(ipart)->x_in().t() );
0497           sh_parton.mass( sh_parton.e()*sh_parton.e() - sh_parton.px()*sh_parton.px() - sh_parton.py()*sh_parton.py() - sh_parton.pz()*sh_parton.pz() );
0498           sh_parton.mass( (sh_parton.mass() >= 0.) ? sqrt(sh_parton.mass()) : sqrt(-sh_parton.mass()) );
0499           sh_parton.col( shower.at(ishower).at(ipart)->color() ); sh_parton.acol( shower.at(ishower).at(ipart)->anti_color() );
0500 
0501           if(shower.at(ishower).at(ipart)->pstat()>-1){
0502         HH_shower.add(sh_parton);
0503         total_shower_energy += HH_shower[HH_shower.num()-1].e();
0504       }else{
0505         neg_ptns.add(sh_parton);
0506         total_shower_energy_neg += neg_ptns[neg_ptns.num()-1].e();
0507       }
0508       }
0509       JSDEBUG<<"Shower#"<<ishower+1 << ". Number of partons to hadronize: " << HH_shower.num();
0510       JSDEBUG<<"Shower#"<<ishower+1 << ". Number of (neg) partons to hadronize: " << neg_ptns.num();
0511   }
0512 
0513   //sample thermal partons, brick or hydro hypersurface
0514     //checking to see if we need to sample thermal partons, if either in brick or hydro
0515     bool runsampler = (((inhydro || inbrick) && HH_thermal.num()==0) || (GetCurrentEvent()%nreusehydro==0)) ? true : false;
0516 
0517   if(runsampler && inbrick){
0518     HH_thermal.clear(); //emptying the thermal partons if we're resampling
0519     ThermalPartonSampler brick(rand_seed); //creating a thermal brick
0520       brick.brick_length_width(brickL,brickL);
0521       brick.brick_flow(0., 0., 0.);
0522     brick.brick_Tc(hydro_Tc);
0523       brick.samplebrick();
0524 
0525       JSINFO << "A " << brickL << " fm brick was sampled, generating " << brick.nTot() << " partons (" << brick.th_nL() << " light, " << brick.th_nS() << " strange).";
0526 
0527       for(int ith=0; ith<brick.nTot(); ++ith){
0528         HHparton thparton;
0529         thparton.is_thermal(true); thparton.id(brick.th_pid(ith)); thparton.orig(1); //sh_parton.string_id(str)
0530       thparton.col(0); thparton.acol(0);
0531         thparton.px(brick.th_px(ith)); thparton.py(brick.th_py(ith)); thparton.pz(brick.th_pz(ith)); thparton.e(  brick.th_e(ith));
0532         thparton.x( brick.th_x(ith) ); thparton.y( brick.th_y(ith) ); thparton.z( brick.th_z(ith) ); thparton.x_t(brick.th_t(ith));
0533         thparton.mass( thparton.e()*thparton.e() - thparton.px()*thparton.px() - thparton.py()*thparton.py() - thparton.pz()*thparton.pz() );
0534         thparton.mass( (thparton.mass() >= 0.) ? sqrt(thparton.mass()) : sqrt(-thparton.mass()) );
0535         thparton.pos_str(1);
0536         HH_thermal.add(thparton); //adding this parton to thermal collection
0537       }
0538       //read in thermal partons, THEN do sibling setup...
0539       for(int i=0;i<HH_thermal.num();++i){
0540         HH_thermal[i].sibling(i); HH_thermal[i].string_id(-i);
0541         HH_thermal[i].is_used(true); HH_thermal[i].sibling( findthermalsibling(i, HH_thermal) ); HH_thermal[i].is_used(false);
0542       }
0543   } else if(runsampler && inhydro){
0544     HH_thermal.clear(); //emptying the thermal partons if we're resampling
0545         std::vector<SurfaceCellInfo> surface_cells;
0546     GetHydroHyperSurface(hydro_Tc, surface_cells);
0547     /*std::cout << "\n\n     Surface Cells\n";
0548     for(int icel=0; icel<surface_cells.size(); ++icel){
0549         if(icel % int(surface_cells.size()/100) != 0){continue;}
0550         std::cout << surface_cells[icel].tau << ":" << surface_cells[icel].eta << ":" << surface_cells[icel].x << ":" << surface_cells[icel].y << ",   ";
0551         std::cout << surface_cells[icel].vx << ":" << surface_cells[icel].vy << ":" << surface_cells[icel].vz << ",   ";
0552         std::cout << surface_cells[icel].qgp_fraction << ":" << surface_cells[icel].temperature << ":" << surface_cells[icel].pressure << "\n";
0553     }
0554     std::cout << "\n\n";*/
0555 
0556         //not happy about having to do this, this way, but it is what it is.
0557         std::vector<std::vector<double>> surface;
0558         for(int icel=0; icel<surface_cells.size(); ++icel){
0559             std::vector<double> cell;
0560             cell.push_back(surface_cells[icel].tau); cell.push_back(surface_cells[icel].x); cell.push_back(surface_cells[icel].y); cell.push_back(surface_cells[icel].eta);
0561             cell.push_back(surface_cells[icel].d3sigma_mu[0]); cell.push_back(surface_cells[icel].d3sigma_mu[1]);
0562             cell.push_back(surface_cells[icel].d3sigma_mu[2]); cell.push_back(surface_cells[icel].d3sigma_mu[3]);
0563             cell.push_back(surface_cells[icel].temperature);
0564             cell.push_back(surface_cells[icel].vx); cell.push_back(surface_cells[icel].vy); cell.push_back(surface_cells[icel].vz);
0565             surface.push_back(cell);
0566         }
0567 
0568         ThermalPartonSampler part_samp(rand_seed); //initializing sampler with random seed
0569         part_samp.set_hypersurface(surface);
0570     if(boost_invariant){
0571       part_samp.sample_2p1d(eta_max_boost_inv);
0572     }else{
0573       part_samp.sample_3p1d(Cartesian_hydro);
0574     }
0575 
0576         JSINFO << "Hydro was sampled, generating " << part_samp.nTot() << " partons (" << part_samp.th_nL() << " light, " << part_samp.th_nS() << " strange).";
0577 
0578         for(int ith=0; ith<part_samp.nTot(); ++ith){
0579             HHparton thparton;
0580             thparton.is_thermal(true); thparton.id(part_samp.th_pid(ith)); thparton.orig(1); //sh_parton.string_id(str)
0581             thparton.px(part_samp.th_px(ith)); thparton.py(part_samp.th_py(ith)); thparton.pz(part_samp.th_pz(ith)); thparton.e(  part_samp.th_e(ith));
0582             thparton.x( part_samp.th_x(ith) ); thparton.y( part_samp.th_y(ith) ); thparton.z( part_samp.th_z(ith) ); thparton.x_t(part_samp.th_t(ith));
0583             thparton.mass( thparton.e()*thparton.e() - thparton.px()*thparton.px() - thparton.py()*thparton.py() - thparton.pz()*thparton.pz() );
0584             thparton.mass( (thparton.mass() >= 0.) ? sqrt(thparton.mass()) : sqrt(-thparton.mass()) );
0585             thparton.pos_str(1);
0586             HH_thermal.add(thparton); //adding this parton to thermal collection
0587         }
0588         //read in thermal partons, THEN do sibling setup...
0589         for(int i=0;i<HH_thermal.num();++i){
0590             HH_thermal[i].sibling(i); HH_thermal[i].string_id(-i);
0591             HH_thermal[i].is_used(true); HH_thermal[i].sibling( findthermalsibling(i, HH_thermal) ); HH_thermal[i].is_used(false);
0592         }
0593   }
0594 
0595   if(!inbrick && !inhydro){ //propagate positive and negative partons for time part_prop in vacuum
0596     for(int i_sh=0; i_sh<HH_shower.num(); ++i_sh){
0597       double max_t_dif = part_prop;
0598             double vel[3]; vel[0]=HH_shower[i_sh].px()/HH_shower[i_sh].e(); vel[1]=HH_shower[i_sh].py()/HH_shower[i_sh].e(); vel[2]=HH_shower[i_sh].pz()/HH_shower[i_sh].e();
0599             HH_shower[i_sh].x(HH_shower[i_sh].x() + vel[0]*max_t_dif); HH_shower[i_sh].y(HH_shower[i_sh].y() + vel[1]*max_t_dif); HH_shower[i_sh].z(HH_shower[i_sh].z() + vel[2]*max_t_dif);
0600             HH_shower[i_sh].x_t(HH_shower[i_sh].x_t() + max_t_dif);
0601     }
0602     for(int i_sh=0; i_sh<neg_ptns.num(); ++i_sh){
0603       double max_t_dif = part_prop;
0604             double vel[3]; vel[0]=neg_ptns[i_sh].px()/neg_ptns[i_sh].e(); vel[1]=neg_ptns[i_sh].py()/neg_ptns[i_sh].e(); vel[2]=neg_ptns[i_sh].pz()/neg_ptns[i_sh].e();
0605             neg_ptns[i_sh].x(neg_ptns[i_sh].x() + vel[0]*max_t_dif); neg_ptns[i_sh].y(neg_ptns[i_sh].y() + vel[1]*max_t_dif); neg_ptns[i_sh].z(neg_ptns[i_sh].z() + vel[2]*max_t_dif);
0606             neg_ptns[i_sh].x_t(neg_ptns[i_sh].x_t() + max_t_dif);
0607     }
0608   }
0609 
0610   //checking to see if partons are inside medium, and if so then propagate all partons to hypersurface!
0611     //also can propagate by part_prop time
0612     for(int i_sh=0; i_sh<HH_shower.num(); ++i_sh){
0613         double vel[3]; vel[0]=HH_shower[i_sh].px()/HH_shower[i_sh].e(); vel[1]=HH_shower[i_sh].py()/HH_shower[i_sh].e(); vel[2]=HH_shower[i_sh].pz()/HH_shower[i_sh].e();
0614         double t_dif = 0.;
0615     if(inbrick && HH_shower[i_sh].x_t() < brickL){
0616       t_dif = brickL - HH_shower[i_sh].x_t();
0617     }else if(inhydro){
0618       int i=0;
0619       double temp=999999.;
0620       while(temp > hydro_Tc){
0621               double tnow = HH_shower[i_sh].x_t() + delta_t*double(i);
0622               double xnow = HH_shower[i_sh].x() + vel[0]*delta_t*double(i);
0623               double ynow = HH_shower[i_sh].y() + vel[1]*delta_t*double(i);
0624               double znow = HH_shower[i_sh].z() + vel[2]*delta_t*double(i);
0625               GetHydroCellSignal(tnow, xnow, ynow, znow, check_fluid_info_ptr);
0626               temp = check_fluid_info_ptr->temperature;
0627               if(temp <= hydro_Tc){
0628           t_dif = delta_t*double(i);
0629         }
0630               ++i;
0631           }
0632     }
0633         double max_t_dif = std::max(t_dif,part_prop);
0634         HH_shower[i_sh].x(HH_shower[i_sh].x() + vel[0]*max_t_dif); HH_shower[i_sh].y(HH_shower[i_sh].y() + vel[1]*max_t_dif); HH_shower[i_sh].z(HH_shower[i_sh].z() + vel[2]*max_t_dif);
0635         HH_shower[i_sh].x_t(HH_shower[i_sh].x_t() + max_t_dif);
0636         //JSINFO<<"Parton propagated to: " << HH_shower[i_sh].x() << ", " << HH_shower[i_sh].y() << ", " << HH_shower[i_sh].z() << ", " << HH_shower[i_sh].x_t();
0637     }
0638   //do the same for the negative partons
0639   for(int i_sh=0; i_sh<neg_ptns.num(); ++i_sh){
0640         double vel[3]; vel[0]=neg_ptns[i_sh].px()/neg_ptns[i_sh].e(); vel[1]=neg_ptns[i_sh].py()/neg_ptns[i_sh].e(); vel[2]=neg_ptns[i_sh].pz()/neg_ptns[i_sh].e();
0641         double t_dif = 0.;
0642     if(inbrick && neg_ptns[i_sh].x_t() < brickL){
0643       t_dif = brickL - neg_ptns[i_sh].x_t();
0644     }else if(inhydro){
0645       int i=0;
0646       double temp=999999.;
0647       while(temp > hydro_Tc){
0648               double tnow = neg_ptns[i_sh].x_t() + delta_t*double(i);
0649               double xnow = neg_ptns[i_sh].x() + vel[0]*delta_t*double(i);
0650               double ynow = neg_ptns[i_sh].y() + vel[1]*delta_t*double(i);
0651               double znow = neg_ptns[i_sh].z() + vel[2]*delta_t*double(i);
0652               GetHydroCellSignal(tnow, xnow, ynow, znow, check_fluid_info_ptr);
0653               temp = check_fluid_info_ptr->temperature;
0654               if(temp <= hydro_Tc){
0655           t_dif = delta_t*double(i);
0656         }
0657               ++i;
0658           }
0659     }
0660         double max_t_dif = std::max(t_dif,part_prop);
0661         neg_ptns[i_sh].x(neg_ptns[i_sh].x() + vel[0]*max_t_dif); neg_ptns[i_sh].y(neg_ptns[i_sh].y() + vel[1]*max_t_dif); neg_ptns[i_sh].z(neg_ptns[i_sh].z() + vel[2]*max_t_dif);
0662         neg_ptns[i_sh].x_t(neg_ptns[i_sh].x_t() + max_t_dif);
0663         //JSINFO<<"Parton propagated to: " << neg_ptns[i_sh].x() << ", " << neg_ptns[i_sh].y() << ", " << neg_ptns[i_sh].z() << ", " << neg_ptns[i_sh].x_t();
0664     }
0665 
0666   /*for(int i=0; i<HH_thermal.num(); i++){
0667     std::cout << HH_thermal[i].id() << "," << HH_thermal[i].x_t() << "," << HH_thermal[i].x()
0668     << "," << HH_thermal[i].y() << "," << HH_thermal[i].z() << "," << HH_thermal[i].e()
0669     << "," << HH_thermal[i].px() << "," << HH_thermal[i].py() << "," << HH_thermal[i].pz()
0670     << "," << HH_thermal[i].mass() << std::endl;
0671   }*/
0672 
0673   //separately running over positive and negative partons
0674   for(int pos_ptn = 1; pos_ptn>=0; --pos_ptn){
0675     double tmp_threco = th_recofactor; //need to keep track of th_recofactor (strength) to disable it for negative partons
0676     double tmp_maxB_level = maxB_level; //need to keep track of maxB_level to disable baryon recombination for negative partons
0677     int tmp_reco_hadrons_pythia = reco_hadrons_pythia;
0678     if(pos_ptn == 0){//handling negative partons by wiping shower partons & hadrons, then rerunning with negative partons
0679         pythia.event.reset(); HH_shower.clear(); HH_shower = neg_ptns; //hadrons, remnants, pyremn cleared below
0680 
0681       // if the fragmentation hadrons are given to the afterburner module
0682       // let the negative partons decay here, as they are not propagated in the
0683       // afterburner
0684       if(afterburner_frag_hadrons){
0685         reco_hadrons_pythia = 1;
0686         pythia.readString("HadronLevel:Decay = on");
0687         pythia.init();
0688       }
0689 
0690       //add holes left by used thermal partons to HH_shower
0691       for(int i=0; i<HH_thermal.num(); ++i){
0692         if(HH_thermal[i].is_used()) {
0693           HH_thermal[i].is_used(false);
0694           HH_shower.add(HH_thermal[i]);
0695         }
0696       }
0697 
0698       //add Extrapartons from recomb() of hadrons to HH_shower of negative partons
0699       for(int i=0; i<HH_recomb_extrapartons.num(); ++i){
0700         HH_shower.add(HH_recomb_extrapartons[i]);
0701       }
0702 
0703       if(HH_shower.num() != 0){
0704         th_recofactor = 0.;//killing thermal + negative parton recombination.
0705         maxB_level = -1;//disable baryon recombination for negative partons
0706       } //do this only if there are negative partons, otherwise the baryon recombination would be switched off after the first event without negative partons
0707     }
0708     if(HH_shower.num() == 0){
0709       continue;
0710     } //attempting to handle events/configurations with 0 partons will result in a crash
0711 
0712     int attempt_num = 0; bool run_successfully = false;
0713     while((attempt_num < attempts_max) && (!run_successfully)){
0714         HH_showerptns = HH_shower;
0715         //clearing hadrons and remnants collections
0716         HH_hadrons.clear(); HH_remnants.clear(); HH_pyremn.clear(); HH_pythia_hadrons.clear(); HH_recomb_extrapartons.clear();
0717 
0718         //since we 'might' need to reset the thermal partons (if present!)... because we alter the thermal parton collection in the string repair routine
0719         for(int i=0; i<HH_thermal.num(); ++i){
0720             HH_thermal[i].is_used(false); HH_thermal[i].is_decayedglu(false); HH_thermal[i].is_remnant(false); HH_thermal[i].used_reco(false); HH_thermal[i].used_str(false); HH_thermal[i].is_thermal(true);
0721             HH_thermal[i].orig(1); HH_thermal[i].par(-1); HH_thermal[i].status(0); HH_thermal[i].col(0); HH_thermal[i].acol(0); HH_thermal[i].is_fakeparton(false);
0722             HH_thermal[i].PY_par1(-1); HH_thermal[i].PY_par2(-1); HH_thermal[i].PY_dau1(-1); HH_thermal[i].PY_dau2(-1); HH_thermal[i].PY_stat(23);
0723             HH_thermal[i].string_id(-i); HH_thermal[i].is_strendpt(false); HH_thermal[i].pos_str(1); HH_thermal[i].endpt_id(0);
0724 
0725         if(pos_ptn == 0) {
0726           HH_thermal[i].is_used(true); //set all the thermal partons to is used for negative partons, such that they are not used in the findthermalsibling routine
0727         }
0728         }
0729 
0730         //checking the shower for any color singlet particles to just dump into PYTHIA
0731         //also handling colored non-partonic particles
0732         int i_show=0;
0733         while(i_show<HH_showerptns.num()){
0734             if(HH_showerptns[i_show].id() == 21){++i_show; continue;} //is gluon
0735             else if(std::abs(HH_showerptns[i_show].id()) <= 6){++i_show; continue;} //is quark
0736             else if((std::abs(HH_showerptns[i_show].id()) >= 1103) && (std::abs(HH_showerptns[i_show].id()) <= 5503) && ((HH_showerptns[i_show].id()/10)%10 == 0)){++i_show; continue;} //is diquark
0737             else if(pythia.particleData.colType(HH_showerptns[i_show].id()) == 2){//this is a non-gluon color octet...
0738                 HH_showerptns[i_show].PY_origid(HH_showerptns[i_show].id()); HH_showerptns[i_show].id(21); ++i_show; continue;
0739             }//this is a non-(simple)quark color triplet... (pid 42(scalar leptoquark), 4000001(1-6, excited quarks), and SUSY particles)
0740             else if(std::abs(pythia.particleData.colType(HH_showerptns[i_show].id())) == 1){
0741                 HH_showerptns[i_show].PY_origid( HH_showerptns[i_show].id() );
0742                 HH_showerptns[i_show].id( 1*(2*std::signbit(-pythia.particleData.colType(HH_showerptns[i_show].id()))-1) ); ++i_show; continue;
0743             } //and the two above should catch 'colored technihadrons' too!
0744             else if(HH_showerptns[i_show].id() == 90){HH_showerptns.remove(i_show); continue;} //PYTHIA specific pid for the 'system' as a whole, shouldn't actually be here.  Dumping it.
0745             //is none of the above (a colorless object of some sort (a hadron, photon, lepton...))
0746             HHhadron had; had.id( HH_showerptns[i_show].id() ); had.orig( HH_showerptns[i_show].orig() ); had.mass( HH_showerptns[i_show].mass() );
0747             had.pos(HH_showerptns[i_show].pos()); had.P(HH_showerptns[i_show].P());
0748             HH_hadrons.add(had); HH_showerptns.remove(i_show);
0749         }
0750 
0751         //setting up the strings appropriately for showers - assumes that color tags are set.
0752         //if there are colored particles without set color tags, it will dump those partons in particular into a single string
0753         int num_strings = 0;
0754         stringform();
0755         num_strings = HH_showerptns[HH_showerptns.num()-1].string_id();
0756 
0757       // last attempt in hadronization is done without recombination
0758       double sh_recofactor_store = sh_recofactor;
0759       if(attempt_num == attempts_max -1) {
0760         sh_recofactor = 0.;
0761         if(pos_ptn == 1) {
0762           JSWARN << "Hadronization failed, try without recombination one more time";
0763         } else {
0764           JSWARN << "Hadronization of negative partons failed, try without recombination one more time";
0765         }
0766       }
0767 
0768         //running recombination
0769         recomb();
0770       sh_recofactor = sh_recofactor_store;
0771 
0772         //function to prepare strings for input into PYTHIA8
0773         //will need a final reindexing for py_remn (all PY_par#, PY_dau# will need to be += 1) AFTER this function (either here, or in invoke_py)
0774         //when recursive 'workaround' for large strings is properly handled/removed, then can put this reindexing inside the function
0775         if(HH_remnants.num()){
0776         bool cut = (attempt_num > -1) ? true : false;
0777         stringprep(HH_remnants, HH_pyremn, cut);
0778       }
0779 
0780       //temporary workaround to force all formed hadrons to be final state - so pythia won't overwrite spacetime info
0781         for(int i=0; i<HH_hadrons.num(); ++i){
0782         HH_hadrons[i].is_final(true);
0783       }
0784 
0785       //if negative fakepartons, we set the momenta and energy to zero before giving them to pythia
0786       if (pos_ptn == 0) {
0787         for(int ipart = 0; ipart < HH_pyremn.num(); ipart++) {
0788           if(HH_pyremn[ipart].is_fakeparton()) {
0789             if(HH_pyremn[ipart].id() == 21 && HH_pyremn[ipart].mass() > (2.*pythia.particleData.m0(211) + 0.01)) {
0790               HH_pyremn[ipart].mass(2.*pythia.particleData.m0(211) + 0.01);
0791             }
0792             HH_pyremn[ipart].e(HH_pyremn[ipart].mass());
0793             HH_pyremn[ipart].px(0.);
0794             HH_pyremn[ipart].py(0.);
0795             HH_pyremn[ipart].pz(0.);
0796           }
0797         }
0798       }
0799 
0800         //running remaining partons through PYTHIA8 string fragmentation
0801         run_successfully = invoke_py();
0802 
0803         //for a successful run, go though final hadrons here and set parton parents up
0804       //bring the hadrons to their corresponding pythia mass shell
0805         if(run_successfully){
0806 
0807         //remove all hadrons from HH_hadrons if reco hadrons are put into pythia
0808         //in this case they are already contained in HH_pythia_hadrons
0809         if(reco_hadrons_pythia) {
0810           HH_hadrons.clear();
0811         }
0812 
0813         //add all fragmentation hadrons from pythia to HH_hadrons, now that pythia hadronization was successfull
0814         for(int iHad = 0; iHad < HH_pythia_hadrons.num(); iHad++) {
0815           HH_hadrons.add(HH_pythia_hadrons[iHad]);
0816         }
0817 
0818         bring_hadrons_to_mass_shell(HH_hadrons);
0819 
0820         //hadron propagation (neglect the photons)
0821             for(int iHad=0; iHad<HH_hadrons.num(); ++iHad){
0822               if(std::abs(had_prop) > 0.0001 && HH_hadrons[iHad].id() != 22){ //assumes that hadron will be propagated by more than 0.0001 fm/c in lab frame - can even propagate backwards, if that's something wanted...
0823                   double vel[3]; vel[0]=HH_hadrons[iHad].px()/HH_hadrons[iHad].e(); vel[1]=HH_hadrons[iHad].py()/HH_hadrons[iHad].e(); vel[2]=HH_hadrons[iHad].pz()/HH_hadrons[iHad].e();
0824                   double t_prop = had_prop/sqrt(1. - vel[0]*vel[0] - vel[1]*vel[1] - vel[2]*vel[2]);
0825                     HH_hadrons[iHad].x(HH_hadrons[iHad].x() + vel[0]*t_prop); HH_hadrons[iHad].y(HH_hadrons[iHad].y() + vel[1]*t_prop); HH_hadrons[iHad].z(HH_hadrons[iHad].z() + vel[2]*t_prop);
0826                     HH_hadrons[iHad].x_t(HH_hadrons[iHad].x_t() + had_prop);
0827                   //JSINFO<<"Hadron propagated to: " << HH_hadrons[iHad].x() << ", " << HH_hadrons[iHad].y() << ", " << HH_hadrons[iHad].z() << ", " << HH_hadrons[iHad].x_t();
0828               }
0829             }
0830 
0831         double energy_check = 0.;
0832         for(int iHad = 0; iHad < HH_hadrons.num(); iHad++){
0833           energy_check += HH_hadrons[iHad].e();
0834         }
0835         if(pos_ptn == 1 && (energy_check < 0.99*total_shower_energy)){
0836           run_successfully = false;
0837         }
0838         }
0839       ++attempt_num;
0840     }
0841 
0842     if(!run_successfully){
0843       HH_hadrons.clear();
0844       if(pos_ptn == 1) {
0845         JSWARN << "This event could not be hadronized.";
0846       } else {
0847         JSWARN << "The negative partons of this event could not be hadronized.";
0848       }
0849     }
0850 
0851     // scale the negative hadron energies/momenta such that the energy is
0852     // conserved when subtracting negative hadrons from the positive ones
0853     if(pos_ptn == 0){
0854       if(HH_hadrons.num() > 0){
0855         scale_kinematics_negative_hadrons(HH_hadrons, total_shower_energy-total_shower_energy_neg, energy_hadrons);
0856       }
0857     }
0858 
0859     for(unsigned int iHad=0; iHad<HH_hadrons.num(); ++iHad){
0860         if(HH_hadrons[iHad].is_final()){
0861             //setting status flag => xy -> x=1 reco, x=2 frag; y=1 sh-sh, y=2 sh-th; neg sign means negative hadron
0862         //all colorless particles get fragmentation status labels
0863             int stat = (HH_hadrons[iHad].is_recohad()) ? 810 : 820;
0864           stat += (HH_hadrons[iHad].is_shth()) ? 2 : 1;
0865           stat *= (pos_ptn == 0) ? -1 : 1 ;
0866             int lab = (pos_ptn == 0) ? -1 : 1 ;
0867           int idH = HH_hadrons[iHad].id(); double mH = HH_hadrons[iHad].mass();
0868             FourVector p(HH_hadrons[iHad].P()); FourVector x(HH_hadrons[iHad].pos());
0869             hOut.push_back(std::make_shared<Hadron> (Hadron (lab,idH,stat,p,x,mH)));
0870 
0871         if(pos_ptn == 1){ // used for scaling of negative hadrons
0872           energy_hadrons += HH_hadrons[iHad].e();
0873         }
0874         }
0875     }
0876       th_recofactor = tmp_threco;
0877     maxB_level = tmp_maxB_level;
0878     reco_hadrons_pythia = tmp_reco_hadrons_pythia;
0879     if(pythia_decays == "off"){pythia.readString("HadronLevel:Decay = off"); pythia.init();}
0880     }
0881 }
0882 
0883 // scale the negative hadron energies/momenta such that the energy is
0884 // conserved when subtracting negative hadrons from the positive ones
0885 void HybridHadronization::scale_kinematics_negative_hadrons(hadron_collection& HH_hadrons, double shower_energy, double positive_hadrons_energy){
0886   double negative_hadrons_energy_initial = 0;
0887   for(int i = 0; i < HH_hadrons.num(); i++){
0888     negative_hadrons_energy_initial += HH_hadrons[i].e();
0889   }
0890 
0891   double e_scaling_factor = (positive_hadrons_energy - shower_energy) / negative_hadrons_energy_initial;
0892   if(e_scaling_factor < 0.){
0893     JSDEBUG << "e_scaling_factor negative, hadron energy below parton energy: " << positive_hadrons_energy - shower_energy << "GeV";
0894     return;
0895   }
0896 
0897   for(int i = 0; i < HH_hadrons.num(); i++){
0898     double new_energy = HH_hadrons[i].e() * e_scaling_factor;
0899     if(new_energy > HH_hadrons[i].mass()){
0900       HH_hadrons[i].e(new_energy);
0901       double new_abs_momentum = std::sqrt(new_energy*new_energy - HH_hadrons[i].mass()*HH_hadrons[i].mass());
0902       double p_scaling_factor = new_abs_momentum / std::sqrt(HH_hadrons[i].px()*HH_hadrons[i].px()+HH_hadrons[i].py()*HH_hadrons[i].py()+HH_hadrons[i].pz()*HH_hadrons[i].pz());
0903       HH_hadrons[i].px(HH_hadrons[i].px() * p_scaling_factor);
0904       HH_hadrons[i].py(HH_hadrons[i].py() * p_scaling_factor);
0905       HH_hadrons[i].pz(HH_hadrons[i].pz() * p_scaling_factor);
0906     }else{
0907       HH_hadrons[i].e(HH_hadrons[i].mass());
0908       HH_hadrons[i].px(0.0);
0909       HH_hadrons[i].py(0.0);
0910       HH_hadrons[i].pz(0.0);
0911     }
0912   }
0913 }
0914 
0915 void HybridHadronization::convert_color_tags_to_int_type(vector<vector<shared_ptr<Parton>>>& shower){
0916   //check which partons have anti-/color tags larger than the int limit
0917   std::vector<unsigned int> used_tags;
0918   //reduce the upper limit -> the maxtag could fail otherwise, if it becomes larger than maximum int
0919   int max_allowed_tag = std::numeric_limits<int>::max() - 1e6;
0920   for(unsigned int ishower = 0; ishower < shower.size(); ishower++) {
0921       for(unsigned int ipart = 0; ipart < shower.at(ishower).size(); ipart++) {
0922       used_tags.push_back(shower.at(ishower).at(ipart)->color());
0923       used_tags.push_back(shower.at(ishower).at(ipart)->anti_color());
0924     }
0925   }
0926   //remove consecutive duplicates in the sorted vector
0927   std::sort(used_tags.begin(), used_tags.end());
0928   used_tags.resize(std::distance(used_tags.begin(), std::unique(used_tags.begin(), used_tags.end())));
0929 
0930   //count the number of needed tags
0931   std::vector<unsigned int> needed_tags_values;
0932   int number_needed_tags = 0;
0933   for (unsigned int tag : used_tags) {
0934     if (tag > max_allowed_tag) {
0935       needed_tags_values.push_back(tag);
0936       number_needed_tags++;
0937     }
0938   }
0939 
0940   //find the first free tag that is not yet used
0941   int lower_limit_tag = 100;
0942   std::vector<int> new_tags;
0943   while (new_tags.size() < number_needed_tags) {
0944       if (std::find(used_tags.begin(), used_tags.end(), lower_limit_tag) == used_tags.end()) {
0945           new_tags.push_back(lower_limit_tag);
0946       }
0947       lower_limit_tag++;
0948   }
0949 
0950   //exchange the tags which are too large by the new ones
0951   for(int tag = 0; tag < number_needed_tags; tag++) {
0952     for(unsigned int ishower = 0; ishower < shower.size(); ishower++) {
0953         for(unsigned int ipart = 0; ipart < shower.at(ishower).size(); ipart++) {
0954         unsigned int current_tag = needed_tags_values.at(tag);
0955         if (shower.at(ishower).at(ipart)->color() == current_tag) {
0956           shower.at(ishower).at(ipart)->set_color(new_tags.at(tag));
0957         }
0958         if (shower.at(ishower).at(ipart)->anti_color() == current_tag) {
0959           shower.at(ishower).at(ipart)->set_anti_color(new_tags.at(tag));
0960         }
0961       }
0962     }
0963   }
0964 }
0965 
0966 //was used in the pygen code to create ordered strings (and assigned string ids) from color tags
0967 //currently has junction functionality commented out until I know how to incorporate it within JETSCAPE
0968 //junction functionality WILL be needed in the event that any given string configurations contain them!
0969 void HybridHadronization::stringform(){
0970 
0971     int nstr=1;
0972 
0973     for(int i=0; i<HH_showerptns.num(); ++i){
0974         if(HH_showerptns[i].string_id() != 0){continue;}
0975 
0976         std::vector<int> colors;
0977         if(HH_showerptns[i].col()  > 0){colors.push_back(HH_showerptns[i].col()) ;}
0978         if(HH_showerptns[i].acol() > 0){colors.push_back(HH_showerptns[i].acol());}
0979         HH_showerptns[i].string_id(nstr); ++nstr;
0980         bool newcolor = true;
0981         while(newcolor){
0982             newcolor = false;
0983             //checking all final particles not in a string for new color id matches...
0984             int j=0; while(j<HH_showerptns.num()){
0985                 if(HH_showerptns[j].string_id() != 0){++j; continue;}
0986                 for(int k=0;k<colors.size();++k){
0987                     if(     colors[k]==HH_showerptns[j].col()  && (HH_showerptns[j].acol()>0)){
0988                         colors.push_back(HH_showerptns[j].acol()); newcolor=true; HH_showerptns[j].string_id(HH_showerptns[i].string_id()); j=-1; break;
0989                     }
0990                     else if(colors[k]==HH_showerptns[j].acol() && (HH_showerptns[j].col() >0)){
0991                         colors.push_back(HH_showerptns[j].col()) ; newcolor=true; HH_showerptns[j].string_id(HH_showerptns[i].string_id()); j=-1; break;
0992                     }
0993                     else if(colors[k]==HH_showerptns[j].col() || colors[k]==HH_showerptns[j].acol()){HH_showerptns[j].string_id(HH_showerptns[i].string_id()); break;}
0994                 }
0995                 ++j;
0996             }
0997             /* //this code WILL be needed in the event that any input string configurations contain junctions!
0998             //checking all the junctions in the event to see if there are any new color id matches...
0999             for(int iJun=0;iJun<pythia.event.sizeJunction();++iJun){
1000                 bool thisjuncolors = false;
1001                 for(int j=0;j<3;++j){for(int k=0;k<colors.size();++k){if(colors[k]==pythia.event.colJunction(iJun, j)){thisjuncolors=true;}}}
1002                 if(!thisjuncolors){continue;}
1003                 for(int j=0;j<3;++j){
1004                     bool addcolor = true;
1005                     for(int k=0;k<colors.size();++k){if(colors[k]==pythia.event.colJunction(iJun,j)){addcolor = false; break;}}
1006                     if(addcolor){colors.push_back(pythia.event.colJunction(iJun,j)); newcolor=true;}
1007                 }
1008             }
1009             */
1010         }
1011     }
1012 
1013     //now, finding all partons in string 'i'(out of nstr-1 total strings) and reordering them
1014     //for "string" i=0 final partons - these are noncolored particles that should just be written out as-is (shouldn't actually be present...)
1015     for(int i=1;i<nstr;++i){
1016 
1017         std::vector<bool> is_used; std::vector<int> ptns_new;
1018         std::vector<int> ptns_strnow;
1019         for(int j=0; j<HH_showerptns.num(); ++j){if(HH_showerptns[j].string_id()==i){ptns_strnow.push_back(j); is_used.push_back(false);}}
1020         //std::vector<int> usedJuns; for(int j=0; j<NumJunctions; ++j){usedJuns.push_back(false);} int numJunsused = 0;
1021 
1022         //find 'a' quark in the event, if there are none, just grab a gluon.
1023         std::vector<int> stack;
1024         bool readcolor=true; int firstcol = 0;
1025         for(int j=0;j<ptns_strnow.size();++j){
1026             if(!(HH_showerptns[ptns_strnow[j]].id() == 21)){
1027                 if((HH_showerptns[ptns_strnow[j]].id() > 0 && HH_showerptns[ptns_strnow[j]].id() <= 6) || (HH_showerptns[ptns_strnow[j]].id() < -6)){
1028                     stack.push_back(ptns_strnow[j]); is_used[j]=true; firstcol=HH_showerptns[stack[0]].acol(); break;
1029                 }
1030                 else{stack.push_back(ptns_strnow[j]); is_used[j]=true; firstcol=HH_showerptns[stack[0]].col(); readcolor=false; break;}
1031             }
1032             //gluon loop catch
1033             else if(j==ptns_strnow.size()-1){stack.push_back(ptns_strnow[0]); is_used[0]=true; firstcol=HH_showerptns[stack[0]].acol();}
1034         }
1035         ptns_new.push_back(stack[0]);
1036 
1037         while(stack.size()>0){
1038 
1039             //catching the end of either a string/junction leg or we've circled back on a gluon loop.
1040             if(      readcolor && (HH_showerptns[stack.back()].col()  == firstcol)){stack.pop_back(); continue;}
1041             else if(!readcolor && (HH_showerptns[stack.back()].acol() == firstcol)){stack.pop_back(); continue;}
1042 
1043             //keeping track if we've added (a) new parton(s) to the stack
1044             bool found=false;
1045 
1046             for(int j=0;j<ptns_strnow.size();++j){
1047                 if(      readcolor && !is_used[j] && (HH_showerptns[stack.back()].col()  == HH_showerptns[ptns_strnow[j]].acol())){
1048                     stack[stack.size()-1] = ptns_strnow[j]; is_used[j]=true; ptns_new.push_back(stack.back()); //--stack.size(); ++stack.size();
1049                     found=true; break;
1050                 }
1051                 else if(!readcolor && !is_used[j] && (HH_showerptns[stack.back()].acol() == HH_showerptns[ptns_strnow[j]].col() )){
1052                     stack[stack.size()-1] = ptns_strnow[j]; is_used[j]=true; ptns_new.push_back(stack.back()); //--stack.size(); ++stack.size();
1053                     found=true; break;
1054                 }
1055             }
1056 
1057             //this code WILL be needed in the event that any input string configurations contain junctions!
1058       /*if(!found && ((pythia.event.sizeJunction() - numJunsused) > 0)){
1059                 int iJun(0), iCol(0);
1060                 if(readcolor){
1061                     for(int iJ=0;iJ<pythia.event.sizeJunction();++iJ){
1062                         if(usedJuns[iJ]){continue;}
1063                         for(int iC=0;iC<3;++iC){if(pythia.event.colJunction(iJ,iC)==HH_showerptns[stack.back()].col() ){iJun=iJ;iCol=iC;found=true;break;}}if(found){break;}
1064                     }
1065                 }
1066                 else{
1067                     for(int iJ=0;iJ<pythia.event.sizeJunction();++iJ){
1068                         if(usedJuns[iJ]){continue;}
1069                         for(int iC=0;iC<3;++iC){if(pythia.event.colJunction(iJ,iC)==HH_showerptns[stack.back()].acol()){iJun=iJ;iCol=iC;found=true;break;}}if(found){break;}
1070                     }
1071                 }
1072 
1073                 //find the next two partons here to add to the stack
1074                 if(found){
1075                     usedJuns[iJun] = true; ++numJunsused;
1076                     readcolor = !readcolor;
1077 
1078                     int cols[2]={0,0};
1079                     int offset=0; for(int j=0;j<3;++j){if(j==iCol){offset=1;continue;} cols[j-offset]=pythia.event.colJunction(iJun,j);}
1080                     if(cols[0]>cols[1]){int temp=cols[0]; cols[0]=cols[1]; cols[1]=temp;}
1081 
1082                     if(readcolor){
1083                         for(int j=0;j<ptns_strnow.size();++j){if(!is_used[j] && (cols[0]==HH_showerptns[ptns_strnow[j]].acol())){
1084                             stack[stack.size()-1] = ptns_strnow[j]; is_used[j]=true; ptns_new.push_back(stack.back()); //--stack.size(); ++stack.size();
1085                             break;
1086                         }}
1087                         for(int j=0;j<ptns_strnow.size();++j){if(!is_used[j] && (cols[1]==HH_showerptns[ptns_strnow[j]].acol())){
1088                             stack.push_back(ptns_strnow[j]); is_used[j]=true; ptns_new.push_back(stack.back()); //--stack.size(); ++stack.size();
1089                             break;
1090                         }}
1091                     }
1092                     else{
1093                         for(int j=0;j<ptns_strnow.size();++j){if(!is_used[j] && (cols[0]==HH_showerptns[ptns_strnow[j]].col())){
1094                             stack[stack.size()-1] = ptns_strnow[j]; is_used[j]=true; ptns_new.push_back(stack.back()); //--stack.size(); ++stack.size();
1095                             break;
1096                         }}
1097                         for(int j=0;j<ptns_strnow.size();++j){if(!is_used[j] && (cols[1]==HH_showerptns[ptns_strnow[j]].col())){
1098                             stack.push_back(ptns_strnow[j]); is_used[j]=true; ptns_new.push_back(stack.back()); //--stack.size(); ++stack.size();
1099                             break;
1100                         }}
1101                     }
1102                 }
1103             }*/
1104             if(!found){stack.pop_back();}
1105         }
1106 
1107         //ordering this string
1108         int endpt = 0;
1109         for(int j=0;j<ptns_new.size();++j){
1110             HH_showerptns[ptns_new[j]].pos_str(j);
1111             HH_showerptns[ptns_new[j]].endpt_id( (HH_showerptns[ptns_new[j]].id() == 21) ? 0 : ++endpt );
1112             HH_showerptns[ptns_new[j]].is_strendpt( (HH_showerptns[ptns_new[j]].id() == 21) ? false : true );
1113         }
1114     }
1115 
1116     //handling any remaining colored objects that have not had color tags set
1117     //these are all just thrown into a single string, which may be 'cut' up later on in the string_prep function
1118     //these will not be 'ordered' within the string nicely...
1119     int numendpoint = 0; int num_str0 = -1;
1120     for(int i=0;i<HH_showerptns.num();++i){
1121         if(HH_showerptns[i].string_id() != 0){continue;}
1122         int iendpoint = 0;
1123         bool is_endpoint = false;
1124         if(HH_showerptns[i].id() != 21){iendpoint = ++numendpoint; is_endpoint = true;}
1125         HH_showerptns[i].string_id(0);
1126         HH_showerptns[i].pos_str(++num_str0);
1127         HH_showerptns[i].endpt_id(iendpoint);
1128         HH_showerptns[i].is_strendpt(is_endpoint);
1129     }
1130 
1131     //reordering HH_showerptns - based on string, and position in the string
1132     //isn't strictly necessary to do this here, as the critical pos_str and endpt_id variables have been set, but is 'nice'
1133     //std::stable_sort(&HH_showerptns[0], (&HH_showerptns[HH_showerptns.num()-1])+1, strid_compare);
1134     std::stable_sort(&HH_showerptns[0], (&HH_showerptns[HH_showerptns.num()-1])+1, [](const HHparton& parton1, const HHparton& parton2){return (parton1.string_id() < parton2.string_id());});
1135     //now that the list is sorted based on string id, going to sort the partons in each string based on the position of the partons in the string
1136     for(int i=0; i<HH_showerptns.num(); ++i){
1137         int start, prev_pos, cur_pos, lastfix;
1138         lastfix = 0; if(i == HH_showerptns.num()-1){lastfix = 1;}
1139         cur_pos = HH_showerptns[i].string_id();
1140         if(i==0){prev_pos = HH_showerptns[0].string_id(); start = 0;}
1141         if(cur_pos != prev_pos || i == HH_showerptns.num()-1){
1142             std::stable_sort(&HH_showerptns[start],&HH_showerptns[i]+lastfix, [](const HHparton& parton1, const HHparton& parton2){return (parton1.pos_str() < parton2.pos_str());});
1143             start = i; prev_pos = HH_showerptns[i].pos_str();
1144         }
1145     }
1146 }
1147 
1148 void HybridHadronization::recomb(){
1149 
1150   //parton list for treating thermal siblings for string repair
1151   parton_collection Extraparton;
1152 
1153     //declaring a few needed values (based on values in init)
1154     double hbarc2 = hbarc*hbarc;
1155 
1156     //should create a new parton collection here, one with only shower quarks (inc. from gluon splitting)
1157     //to consider for recombination - then afterwards can reform gluons and output remnants
1158     parton_collection showerquarks;
1159 
1160     //clearing remnants, in case it hasn't been done before
1161     HH_remnants.clear();
1162 
1163     //constructing a list of all the strings in the event
1164     std::vector<int> list_strs;
1165     //adding the first string to the list
1166     list_strs.push_back(HH_showerptns[0].string_id());
1167     //looping over all the partons in the event, and writing each 'unique' string to the list
1168     for(int i=0;i<HH_showerptns.num();++i){
1169         bool str_match = false;
1170         for(int j=0;j<list_strs.size();++j){
1171             if(HH_showerptns[i].string_id() == list_strs[j]){str_match = true;}
1172         }
1173         if(!str_match){list_strs.push_back(HH_showerptns[i].string_id());}
1174     }
1175 
1176   //*********************************************************************************************************************
1177   //        Splitting gluons into q-qbar pairs for recombination
1178   //*********************************************************************************************************************
1179 
1180   //std::cout <<"Below is Color information of all particles in the String (Col, Acol)"<<endl;
1181   std::vector<int*> ColInfo3;
1182   for(int i=0; i<HH_showerptns.num(); i++) {
1183     int colinfo3[2] = {HH_showerptns[i].col() , HH_showerptns[i].acol()};
1184       ColInfo3.push_back(colinfo3);
1185       //std::cout <<" ( "<<HH_showerptns[i].string_id()<<" , "<<ColInfo3.at(i)[0]<<"   "<<ColInfo3.at(i)[1]<<"  ) ";
1186   }
1187   //std::cout <<endl;
1188 
1189   //while running PythiaBrickTest, error{same col tags and acol tag for the different particles, somehow the cause would be in MATTER in determining the color tag} detected,
1190   //So, If there are problems from the initial structure, correct it based on the color flow.
1191   int temptag = 1;
1192   for(int i = 0; i < HH_showerptns.num(); i++){
1193     for(int j = i+1; j < HH_showerptns.num(); j++){
1194       if(HH_showerptns[i].col() != 0 && HH_showerptns[i].col() == HH_showerptns[j].col()){ //same col tag for different particles detected.
1195         for(int k = 0; k < HH_showerptns.num(); k++){
1196           if(HH_showerptns[i].col() == HH_showerptns[k].acol()){
1197             vector<int> Info;// location of i, location of k, temp color tag will be saved in this vector.
1198             Info.push_back(i);
1199             Info.push_back(k);
1200             Info.push_back(temptag);
1201 
1202             HH_showerptns[i].col(temptag);
1203             HH_showerptns[k].acol(temptag); //apply the change for the col, acol pair to preserve the color flow with least impact to the final result.
1204             temptag++;
1205             Info.clear();
1206           }
1207         }
1208       }
1209     }
1210   }
1211 
1212   for(int i = 0; i < HH_showerptns.num(); i++){
1213     for(int j = i+1; j < HH_showerptns.num(); j++){
1214       if(HH_showerptns[i].acol() != 0 && HH_showerptns[i].acol() == HH_showerptns[j].acol()){ //same acol tag for different particles detected.
1215         for(int k = 0; k < HH_showerptns.num(); k++){
1216           if(HH_showerptns[i].acol() == HH_showerptns[k].col()){
1217             vector<int> Info;// location of i, location of k, temp color tag will be saved in this vector.
1218             Info.push_back(i);
1219             Info.push_back(k);
1220             Info.push_back(temptag);
1221 
1222             HH_showerptns[i].acol(temptag);
1223             HH_showerptns[k].col(temptag); //apply the change for the col, acol pair to preserve the color flow with least impact to the final result.
1224             temptag++;
1225             Info.clear();
1226           }
1227         }
1228       }
1229     }
1230   }
1231 
1232   //std::cout <<endl;
1233   //std::cout <<"Below is Color information of all particles in the Revised String (Col, Acol)"<<endl;
1234   std::vector<int*> ColInfo2;
1235   for(int i=0; i<HH_showerptns.num(); i++) {
1236     int colinfo2[2] = {HH_showerptns[i].col() , HH_showerptns[i].acol()};
1237     ColInfo2.push_back(colinfo2);
1238     //std::cout <<" ( "<<HH_showerptns[i].string_id()<<" , "<<ColInfo2.at(i)[0]<<"   "<<ColInfo2.at(i)[1]<<"  ) ";
1239   }
1240   //std::cout <<endl;
1241 
1242   set_initial_parton_masses(HH_showerptns);
1243 
1244     //starting with shower partons
1245     for(int i_pt=0; i_pt<HH_showerptns.num(); ++i_pt){
1246         //if parton is a quark, stick it into showerquarks - and set it's parent id to the quark in the original shower
1247         if((std::abs(HH_showerptns[i_pt].id()) <= 5 ) && (HH_showerptns[i_pt].PY_origid() == 0)){
1248       showerquarks.add(HH_showerptns.partons[i_pt]);
1249       showerquarks[showerquarks.num()-1].par(i_pt);
1250     }
1251         //else parton is a gluon, decay into q-qbar and stick those into the collection; set parent id appropriately for both
1252         else if((HH_showerptns[i_pt].id() == 21) && (HH_showerptns[i_pt].PY_origid() == 0)){
1253             //setting is_decayedglu; not going to set used until one of it's quarks has been used
1254             //will set the status to -99 here, this will be changed to -1 after first quark, and to 1 after second
1255             HH_showerptns[i_pt].is_decayedglu(true); HH_showerptns[i_pt].status(-99);
1256 
1257             //choosing a gluon mass - if implemented in the future, can (should) read this from the gluon entry itself (or set if necessary)
1258             //maybe discard gluon if it is under some threshold of mass (eg < pion?)
1259             //temporarily saving previously set mass here - here's a good place to check if this is even necessary?
1260             double temp_glumass = HH_showerptns[i_pt].mass();
1261             if(HH_showerptns[i_pt].mass()<2.*xmq+0.001){HH_showerptns[i_pt].mass(2.*xmq+0.001);}
1262 
1263             //gluon decay function reads in the gluon (and the overwritten random mass), and writes the output q-qbar pair to qpair
1264             parton_collection qpair;
1265             gluon_decay(HH_showerptns[i_pt], qpair);
1266 
1267             //swapping back original gluon mass
1268             HH_showerptns[i_pt].mass(temp_glumass);
1269 
1270             //setting the parents of the q-qbar pair to the original gluon (and other vars appropriately here)
1271             qpair[0].par(i_pt); qpair[1].par(i_pt);
1272             qpair[0].is_shower(true); qpair[1].is_shower(true);
1273             qpair[0].orig( HH_showerptns[i_pt].orig() ); qpair[1].orig( HH_showerptns[i_pt].orig() );
1274             qpair[0].string_id ( HH_showerptns[i_pt].string_id()); qpair[1].string_id ( HH_showerptns[i_pt].string_id());
1275             qpair[0].pos_str   ( HH_showerptns[i_pt].pos_str());   qpair[1].pos_str   ( HH_showerptns[i_pt].pos_str());
1276 
1277             //adding these partons to the collection
1278             showerquarks.add(qpair);
1279 
1280             //setting up the sibling relations in showerquarks
1281             showerquarks[showerquarks.num()-1].sibling( showerquarks.num()-2 );
1282             showerquarks[showerquarks.num()-2].sibling( showerquarks.num()-1 );
1283         }
1284         //else it's not a quark(u,d,s,c,b) or gluon and we're skipping it.
1285         else{
1286             //JSINFO << "\n\nThere is a parton that is not a quark(u,d,s,c,b) or gluon in the input shower.  Skipping parton in recombination.\n\n";
1287         }
1288     }
1289   //*********************************************************************************************************************
1290   //        Finished splitting gluons
1291   //*********************************************************************************************************************
1292 
1293   //*********************************************************************************************************************
1294   //        Beginning of Recombination routine
1295   //*********************************************************************************************************************
1296 
1297     //randomly permute an integer array with 'n' entries from 1 to n (actually from 0 to n-1)
1298     //the array will be used to access the i'th element of the showerquarks collection
1299     //done as showerquarks[perm0_sharray[i]]
1300     //since we have separate shower and thermal arrays, we will force the first quark to always be from the shower
1301     //
1302     //construct perm1 array of size showerquarks.num() and perm2 array of size showerquarks.num() + HH_thermal.num()
1303     //to access an element from either shower or thermal partons
1304     //there will be showerquarks.num() positive entries and HH_thermal.num() negative entries (going to exclude 0 in these, just -1 i's)
1305     //thus, perm2 = { 3, -42, -33,...} will access i=2 from showerquarks, then 41 from thermal, then 32 from thermal...
1306     //
1307     //lastly, need to bypass scenarios where the quark has been used, or we're trying to use the same quark twice
1308     //to determine if we're trying to use the same quark twice, check if perm[i]=perm[j]
1309     //if used=true OR p[i]=p[j]?, then skip this attempt (continue works well for these cases?)
1310 
1311     //constructing permutation arrays; shower quarks are > 0, thermal are < 0
1312     //perm2 will always access element [std::abs(perm2[i]) - 1]
1313     int perm1[showerquarks.num()], perm2[showerquarks.num()+HH_thermal.num()];
1314 
1315   //option to either bias recombination, earlier particles attempt to recombine first
1316     if(torder_reco){
1317         //placeholders to sort by time
1318         std::vector<std::pair<double,int>> tosort1, tosort2;
1319         for (int i=0;i<showerquarks.num();++i){
1320             tosort1.push_back(std::make_pair(showerquarks[i].x_t(),i));
1321             tosort2.push_back(std::make_pair(showerquarks[i].x_t(),i+1));
1322         }
1323         for (int i=0;i<HH_thermal.num();++i){
1324       tosort2.push_back({HH_thermal[i].x_t(),-i-1});
1325     }
1326 
1327         //sorting
1328         std::stable_sort(std::begin(tosort1), std::end(tosort1));
1329         std::stable_sort(std::begin(tosort2), std::end(tosort2));
1330 
1331         //saving order into permutation arrays
1332         for(int i=0;i<tosort1.size();++i){
1333       perm1[i]=tosort1[i].second;
1334     }
1335         for(int i=0;i<tosort2.size();++i){
1336       perm2[i]=tosort2[i].second;
1337     }
1338     }else{
1339         //prepping permutation arrays to be shuffled
1340         for(int i=0;i<showerquarks.num();++i){
1341       perm1[i]=i;
1342     }
1343         for(int i=0;i<HH_thermal.num();++i){
1344       perm2[i]=(i-HH_thermal.num());
1345     }
1346         for(int i=HH_thermal.num();i<showerquarks.num()+HH_thermal.num();++i){
1347       perm2[i]=(i-HH_thermal.num()+1);
1348     }
1349 
1350         //permuting these arrays using Fisher-Yates algorithm
1351         //-- To shuffle an array a of n elements (indices 0..n-1):
1352         //for i from 0 to n−2 do
1353         //  j ← random integer such that i ≤ j < n
1354         //  exchange a[i] and a[j]
1355         for(int i=0;i<showerquarks.num()-1;++i){
1356             int ranelement = i+floor((showerquarks.num()-i)*ran());
1357             int temp = perm1[i];
1358       perm1[i] = perm1[ranelement];
1359       perm1[ranelement] = temp;
1360         }
1361         for(int i=0;i<showerquarks.num()+HH_thermal.num()-1;++i){
1362             int ranelement = i+floor((showerquarks.num()+HH_thermal.num()-i)*ran());
1363             int temp = perm2[i];
1364       perm2[i] = perm2[ranelement];
1365       perm2[ranelement] = temp;
1366         }
1367     }
1368 
1369   //std::cout <<"Below is Color information of all particles in the String (Col, Acol)"<<endl;
1370   std::vector<int*> ColInfo;
1371   for(int i=0; i<HH_showerptns.num(); i++) {
1372     int colinfo[2] = {HH_showerptns[i].col() , HH_showerptns[i].acol()};
1373     ColInfo.push_back(colinfo);
1374     //std::cout <<" ( "<<HH_showerptns[i].string_id()<<" , "<<ColInfo.at(i)[0]<<"   "<<ColInfo.at(i)[1]<<"  ) ";
1375   }
1376   //std::cout <<endl;
1377 
1378   // make all color tags to be indices for the matrix (so the indice represent the color tag, don't need to classify anti or not)
1379   std::vector<vector<int>> IndiceForCol1; // this vector will form vector of vectors(location in the string, anti or not, color tag)
1380   std::vector<int> IndiceForCol2; // this vector is one component of vector above
1381   std::vector<int> IndiceForColFin; // this vector is final vector that'll be used for process
1382 
1383   for(int iIndice=0; iIndice < HH_showerptns.num(); iIndice++) {
1384     IndiceForCol2.push_back(iIndice);
1385     IndiceForCol2.push_back(1);
1386     IndiceForCol2.push_back(HH_showerptns[iIndice].col());
1387     IndiceForCol1.push_back(IndiceForCol2);
1388     IndiceForCol2.clear();
1389 
1390     IndiceForCol2.push_back(iIndice);
1391     IndiceForCol2.push_back(-1);
1392     IndiceForCol2.push_back(HH_showerptns[iIndice].acol());
1393     IndiceForCol1.push_back(IndiceForCol2);
1394     IndiceForCol2.clear();
1395   } // As a result, two vectors with 3 component keep being added to bigger vector, now exclude same tag and zero
1396   //dignostic measure
1397   //std::cout <<endl<<" Below is list of all color tags " <<endl;
1398   //std::cout <<" ( ";
1399   //for (int icheck=0; icheck < IndiceForCol1.size(); icheck++) {
1400     //std::cout << IndiceForCol1.at(icheck).at(2) << " , ";
1401   //}
1402   //std::cout <<" ) " <<endl;
1403 
1404   vector<int> tempcol;
1405   // now put all the values in ColInfo into IndiceForColFin
1406   for(int icol = 0; icol < IndiceForCol1.size(); icol++){
1407     tempcol.push_back(IndiceForCol1.at(icol).at(2));
1408   }
1409   if(tempcol.at(0) != 0){
1410     IndiceForColFin.push_back(tempcol.at(0));
1411   }
1412   if(tempcol.at(1) != 0){
1413     IndiceForColFin.push_back(tempcol.at(1));
1414   }
1415 
1416   for(int iclear1 = 0; iclear1 < tempcol.size(); iclear1++){
1417     bool foundsame = false;
1418     for(int iclear2 = 0; iclear2 < IndiceForColFin.size(); iclear2++){
1419       if(tempcol.at(iclear1) == IndiceForColFin.at(iclear2) || tempcol.at(iclear1) == 0){
1420         foundsame = true;
1421       }
1422     }
1423     if(!foundsame){
1424       IndiceForColFin.push_back(tempcol.at(iclear1));
1425     }
1426     foundsame = false;
1427   }
1428 
1429   //last checking whether there is zero in the color tag list
1430   for(int i = 0; i < IndiceForColFin.size(); i++){
1431     if(IndiceForColFin[i] == 0){
1432       std::vector<int>::iterator i1 = std::find(IndiceForColFin.begin(), IndiceForColFin.end(), 0 );
1433       int distance = std::distance(IndiceForColFin.begin() , i1);
1434       //std::cout <<endl<<" zero is located at "<<distance<<endl;
1435       IndiceForColFin.erase(i1);
1436     }
1437   }
1438 
1439   //dignostic syntax
1440   /*std::cout <<endl<<" Below is list of valid color tags " <<endl;
1441   std::cout <<" ( ";
1442   for (int icheck=0; icheck < IndiceForColFin.size(); icheck++) {
1443     std::cout << IndiceForColFin.at(icheck) << " , ";
1444   }
1445   std::cout <<" ) " <<endl;*/
1446 
1447   //when we includes the partons from LBT, color tags from them are both zero in col and acol tags,
1448   //Therefore, based on the maximum color tag from the parton with col , acol tags, reassign the color tags for LBT partons. As a result, one fake string should be formed based on these color Tags
1449   //First, check the maximum color tags in the vector of valid color tags
1450   int limit;
1451   int maxtag;
1452   maxtag = *max_element(IndiceForColFin.begin() , IndiceForColFin.end()); //this will be so important in dealing thermal partons, beacause they get color tag incremented from this max tag
1453   limit = maxtag; // save initial maxtag for the future usage{It should be used for color reconnection matrix}
1454   //std::cout <<endl<<" max tag is "<<maxtag<<endl;
1455 
1456   // before determine the matrix, need to link color tag with the matrix indices( by color tag and trace back to the particle, then determine the probability) It's done above(IndiceForCol1)
1457   // to define the probability, parameters for distance should exist. possibly, that could be the par() or string number the last
1458   std::vector<vector<double>> MesonrecoMatrix1; // vector of double (prob) , ,,,// in a big scheme, these two vector form a Matrix
1459   std::vector<double> MesonrecoMatrix2; // this is 1d vector of (probabilty)
1460 
1461   //first, Form Meson recombination Matrix
1462   for(int irow=0; irow < IndiceForColFin.size(); irow++){
1463     for(int icol=0; icol < IndiceForColFin.size(); icol++){
1464       double Mesonfactor;
1465       int distance; // distance between the color tags in string(not c++ function)
1466       int tag1 = IndiceForColFin.at(irow);
1467       int tag2 = IndiceForColFin.at(icol);
1468       std::vector<int>::iterator it1 = std::find(IndiceForColFin.begin(), IndiceForColFin.end(), tag1);
1469       std::vector<int>::iterator it2 = std::find(IndiceForColFin.begin(), IndiceForColFin.end(), tag2);// set up for finding the location of co tag in vector that will be used to find distance
1470       int pos1 = std::distance(IndiceForColFin.begin(), it1); //location of col tag of irow
1471       int pos2 = std::distance(IndiceForColFin.begin(), it2); //location of col tag of icol
1472       //std::cout <<endl<<"position of "<<IndiceForColFin.at(irow)<<" is " << pos1 <<endl;
1473       //std::cout <<endl<<"position of "<<IndiceForColFin.at(icol)<<" is " << pos2 <<endl;
1474 
1475       distance = abs(pos1 - pos2);
1476       //std::cout <<endl<<" At ( "<<irow<<","<<icol<<" ) , distance is "<<distance<<endl;
1477       if(distance == 0) {
1478         Mesonfactor = 1;
1479         //std::cout <<endl<<"Temp Meson Factor is "<<Mesonfactor<<endl;
1480         MesonrecoMatrix2.push_back(Mesonfactor);
1481       };
1482       if(distance > 0) {
1483         Mesonfactor = 0.111;
1484         //std::cout <<endl<<"Temp Meson Factor is "<<Mesonfactor<<endl;
1485         MesonrecoMatrix2.push_back(Mesonfactor);
1486       };
1487     }
1488     MesonrecoMatrix1.push_back(MesonrecoMatrix2);
1489     MesonrecoMatrix2.clear();
1490   }
1491 
1492   // now correct the component in MesonMatrix1 by searching through HH_showerptns{checking gluon}
1493   for(int icheck1 = 0; icheck1 < HH_showerptns.num(); icheck1++ ){
1494     if(HH_showerptns[icheck1].col() != 0 && HH_showerptns[icheck1].acol() != 0 ){//finding gluon means that finding partons that can't form color singlet, but octet
1495       int tag1 = HH_showerptns[icheck1].col();
1496       int tag2 = HH_showerptns[icheck1].acol();
1497       std::vector<int>::iterator it1 = std::find(IndiceForColFin.begin(), IndiceForColFin.end(), tag1);
1498       std::vector<int>::iterator it2 = std::find(IndiceForColFin.begin(), IndiceForColFin.end(), tag2);// set up for finding the location of co tag in vector that will be used to find distance
1499       int pos1 = std::distance(IndiceForColFin.begin(), it1); //location of col tag of irow
1500       int pos2 = std::distance(IndiceForColFin.begin(), it2); //location of col tag of icol
1501       MesonrecoMatrix1.at(pos1).at(pos2) = 0;
1502       MesonrecoMatrix1.at(pos2).at(pos1) = 0;
1503     }
1504   }
1505   /*
1506   //dignostic measure
1507   std::cout <<endl<<"Meson reco Matrix is same as below"<<endl;
1508   for(int irow=0; irow < IndiceForColFin.size(); irow++){
1509     for(int icol=0; icol < IndiceForColFin.size(); icol++){
1510       std::cout <<"  "<<MesonrecoMatrix1.at(irow).at(icol)<<"  ";
1511     }
1512     std::cout <<endl<<endl;
1513   }
1514   */
1515   //MesonrecoMatrix is Formed so far, Now make that of Baryon!!
1516 
1517   std::vector<vector<vector<double>>> BaryonrecoMatrix1; // vector of double (prob) , ,,,// in a big scheme, these three items form a Matrix of vector
1518   std::vector<vector<double>> BaryonrecoMatrix2; // this is vector of 2d vector below (probabilty, required color charge for color neutrality), ( , ) , ( , ) ...
1519   std::vector<double> BaryonrecoMatrix3; // this is 2d vector of (probabilty, required color charge for color neutrality)
1520 
1521   for(int irow=0; irow < IndiceForColFin.size(); irow++){
1522     for(int icol=0; icol < IndiceForColFin.size(); icol++){
1523       double Baryonfactor;
1524       BaryonrecoMatrix3.push_back(1./27.);//1/27: probability to get singlet state
1525       BaryonrecoMatrix3.push_back(0.); // now the probability factor and color(not specified yet, it'll be done with baryon formation) for neutrality are saved.
1526 
1527       BaryonrecoMatrix2.push_back(BaryonrecoMatrix3);
1528       BaryonrecoMatrix3.clear();
1529     }
1530     BaryonrecoMatrix1.push_back(BaryonrecoMatrix2);
1531     BaryonrecoMatrix2.clear();
1532   }
1533   /*
1534   //dignostic measure
1535   std::cout <<endl<<"Baryon reco Matrix is same as below"<<endl;
1536   for(int irow=0; irow < IndiceForColFin.size(); irow++){
1537     for(int icol=0; icol < IndiceForColFin.size(); icol++){
1538       std::cout <<"  ( "<<BaryonrecoMatrix1.at(irow).at(icol).at(1)<<" )  ";
1539     }
1540     std::cout <<endl<<endl;
1541   }
1542   //std::cout <<endl<<endl;
1543   */
1544 
1545     //looping over all the quarks that we have...
1546     //'q1' loops over all quarks in the shower
1547     //'q2' loops over all quarks in the event
1548     //'q3' loops over all quarks in the event, starting from 'q2' and ending at the last quark
1549     //when 'q2' is at the last quark, we will not consider quark 'q3' - can only make a meson at that point...
1550 
1551     parton_collection considering;
1552   int element[3];
1553 
1554     for(int q1=0;q1<showerquarks.num();++q1){
1555         //accessing first considered quark
1556         //set q1 variables here
1557 
1558         if(sh_recofactor < 0.0000000001){continue;} //turning off recombination in a computationally friendly way...
1559 
1560         //resetting madehadron flag, now that we're going to be considering a new hadron
1561         bool madehadron = false;
1562 
1563         //taking the id from the permutation array, and turning it into quark array element
1564         element[0] = perm1[q1];
1565 
1566         //skipping if current quark has been used or isn't a u,d,s,c,b quark or antiquark
1567         if(showerquarks[element[0]].status() != 0 || showerquarks[element[0]].is_used()){continue;}
1568         else if(std::abs(showerquarks[element[0]].id()) > 5){JSWARN << "SOMETHING OTHER THAN u,d,s,c,b WAS considered for recombination, THIS SHOULD NOT HAPPEN!"; continue;}
1569 
1570         //assigning quark values to considering - and setting the status to -991
1571         //if at the end of the check, we make a hadron, we will set all -99* entries to 1, else we'll set back to 0
1572 
1573         considering.add(showerquarks[element[0]]);
1574         showerquarks[element[0]].status(-991);
1575 
1576         for(int q2=0;q2<showerquarks.num()+HH_thermal.num();++q2){
1577             //set q2 variables here - if we can form a meson, then skip q3 loop
1578             //also skip q3 loop if q2 is at last quark
1579 
1580       double recofactor2 = 1./9.;
1581 
1582             //accessing the second considered quark
1583             //this will skip over non-quark entries in HH_thermal
1584             if(perm2[q2]>0){/*is shower quark*/ element[1] = perm2[q2] - 1;}
1585             else{/*is thermal quark*/ element[1] = perm2[q2] + 1;}
1586 
1587             //checking to see if quark is in shower or thermal
1588             //only need to check if quark is the same as the previous quark IFF it is in the shower
1589             //only need to check if quark is from the same gluon if it is from a gluon decay in the shower...
1590             //want to check if we've messed up and are accessing a gluon if it is in original shower/thermal
1591             //need to check if used for all cases...
1592             if(perm2[q2]>0){
1593                 //skipping if current quark has been used
1594                 if(showerquarks[element[1]].status() != 0 || showerquarks[element[1]].is_used()){continue;}
1595                 //skipping if current quark is the same as q1
1596                 else if(element[0]==element[1]){continue;}
1597                 //skipping if the current quark is from the same gluon as q1
1598                 else if((showerquarks[element[0]].par() != -1) && (showerquarks[element[0]].par() == showerquarks[element[1]].par())){continue;}
1599                 //skipping if the current quark is not in the same string as q1 (both are shower partons)
1600                 //else if(showerquarks[element[1]].string_id() != showerquarks[element[0]].string_id()){continue;}
1601                 //skipping if current quark is not a u,d,s,c,b quark
1602                 else if(std::abs(showerquarks[element[1]].id()) > 5){JSWARN << "SOMETHING OTHER THAN u,d,s,c,b WAS considered for recombination, THIS SHOULD NOT HAPPEN!"; continue;}
1603 
1604                 considering.add(showerquarks[element[1]]);
1605                 showerquarks[element[1]].status(-992);
1606             }
1607             else if(perm2[q2]<0){
1608                 //skipping if current quark has been used
1609                 if(HH_thermal[-element[1]].status() != 0 || HH_thermal[-element[1]].is_used()){continue;}
1610                 //skipping if current quark is not a u,d,s,c,b quark
1611                 else if(std::abs(HH_thermal[-element[1]].id()) > 5){JSWARN << "SOMETHING OTHER THAN u,d,s,c,b WAS considered for recombination, THIS SHOULD NOT HAPPEN!"; continue;}
1612                 //turning off recombination for thermal partons in a computationally friendly way...
1613                 else if(th_recofactor < 0.001){continue;}
1614 
1615                 //checking distance cut ONLY if this is a thermal parton - skip if dist2 > dist2cut
1616                 FourVector pos_ptn1 = considering[0].pos(); FourVector pos_ptn2 = HH_thermal[-element[1]].pos();
1617                 double dt = pos_ptn1.t() - pos_ptn2.t();
1618                 if(dt > 0.){
1619                     double dt_E = dt/HH_thermal[-element[1]].e(); // P/E * dT = dist = P*(dT/E)
1620                     pos_ptn2.Set(pos_ptn2.x()+HH_thermal[-element[1]].px()*dt_E,pos_ptn2.y()+HH_thermal[-element[1]].py()*dt_E,pos_ptn2.z()+HH_thermal[-element[1]].pz()*dt_E,0.);
1621                 }
1622                 else{
1623                     double dt_E = -dt/considering[0].e();
1624                     pos_ptn1.Set(pos_ptn1.x()+considering[0].px()*dt_E,pos_ptn1.y()+considering[0].py()*dt_E,pos_ptn1.z()+considering[0].pz()*dt_E, 0.);
1625                 }
1626                 if(dif2(pos_ptn1,pos_ptn2) > dist2cut){continue;}
1627 
1628                 considering.add(HH_thermal[-element[1]]);
1629                 HH_thermal[-element[1]].status(-992);
1630             }
1631             else{JSWARN << "SOMETHING WENT HORRIBLY WRONG - DO NOT KNOW WHERE CURRENT QUARK CAME FROM?!";}
1632 
1633             //now that we have two 'acceptable' quarks to check hadron formation against,
1634             //there is no reason to bother checking if we can make a baryon if we have a q-qbar at this point...
1635             //will skip third loop in this case - otherwise we will check if we can make a baryon...
1636             if((considering[0].id()*considering[1].id() > 0) && (q2 < showerquarks.num()+HH_thermal.num()-1) && (maxB_level > -1)){
1637         for(int q3=q2+1;q3<showerquarks.num()+HH_thermal.num();++q3){
1638 
1639           double recofactor3 = 2./27.;
1640 
1641                   //removing all but the first two entries in the considering collection...
1642                   //this should have been done before, but have this here just in case - remove if this doesn't ever trigger
1643                   while(considering.num() > 2){considering.partons.pop_back();}
1644 
1645                   //accessing the third considered quark
1646                   //this will skip over non-quark entries in HH_thermal
1647                   if(perm2[q3]>0){/*is shower quark*/ element[2] = perm2[q3] - 1;}
1648                   else{/*is thermal quark*/ element[2] = perm2[q3] + 1;}
1649 
1650                   //now that we have q3, we need to check if it is valid:
1651                   //q3 needs to be checked if used (all cases)
1652                   //q3 needs to be checked if it is a erroneously accessed parton (not u,d,s,c,b quark)
1653                   //q3 needs to be checked against q1 to see if it is the same, or from the same gluon
1654                   //q3 does not need to be checked against q2 to see if it is the same
1655                   //q3 does need to be checked to see if it is from the same gluon as q2
1656                   //q3 needs to be checked to make sure that it can form a baryon with q1 and q2 (checking against either is ok)
1657                   //check:  used, sameq1, sameg_q1, sameg_q2, isglu
1658                   if(perm2[q3]>0){
1659                     //skipping if the current quark cannot make a baryon with other two quarks
1660                     if(showerquarks[element[2]].id()*considering[0].id() < 0){continue;}
1661                     //skipping if current quark has been used
1662                     if(showerquarks[element[2]].status() != 0 || showerquarks[element[2]].is_used()){continue;}
1663                     //skipping if current quark is the same as q1
1664                     else if(element[0]==element[2] || element[1] == element[2]){continue;}
1665                     //skipping if the current quark is from the same gluon as q1
1666                     else if((showerquarks[element[0]].par() != -1) && (showerquarks[element[0]].par() == showerquarks[element[2]].par())){continue;}
1667                     //skipping if the current quark is from the same gluon as q2
1668                     else if((perm2[q2] > 0) && (showerquarks[element[1]].par() != -1) && (showerquarks[element[1]].par() == showerquarks[element[2]].par())){continue;}
1669                     //skipping if the current quark is not in the same string as q1
1670                     //(q2 MUST be in the same string as q1 if it's in the shower, and doesn't need to be checked if thermal)
1671                     //else if(showerquarks[element[2]].string_id() != showerquarks[element[0]].string_id()){continue;}
1672                     //skipping if current quark is not a u,d,s,c,b quark
1673                     else if(std::abs(showerquarks[element[2]].id()) > 5){JSWARN << "SOMETHING OTHER THAN u,d,s,c,b WAS considered for recombination, THIS SHOULD NOT HAPPEN!"; continue;}
1674 
1675                     considering.add(showerquarks[element[2]]);
1676                     showerquarks[element[2]].status(-993);
1677 
1678             //TODO: Here we need to establish the probability about baryon formation. first, need to find 3sets of col tag pair are included junction info at the same time. if all 3 does, prob is 1/27, if 1 does, find other component's tag with element[2](3rd one)'s in Meson Matrix!
1679             //second, scan all junction lists
1680             //before that, we need to evaluate temporary junction, because some junctions could be eliminated, So need to make tempjunction list. then we need to proocedure to erase the factor in the vectors!
1681             //Now evaluating the Tempjunctions element first, before this, declare bool variables for the next proocedure
1682             bool element1 = false;
1683             bool element2 = false;
1684             bool element3 = false;
1685             int juncnum1 = 999999999;
1686             int juncnum2 = 999999999;
1687             int juncnum3 = 999999999;
1688 
1689             int standard = IndiceForColFin.size(); // to apply the "if" statement, set the condition for later syntax
1690             int tagformatrix = 999999999; // if all three tags are in same junction, we need to set large number not to confuse, this will be filtered by later syntax
1691             int loc1 = standard; //location in the MesonrecoMatrix
1692             std::vector<int>::iterator I1;
1693             std::vector<int>::iterator I2;
1694             int loc2 = standard;
1695 
1696             if(considering[0].id()*considering[1].id()*considering[2].id() > 0){
1697               // baryon case, and this will check whether two particles are in same junction and the other is not.
1698               // and evaluate(by mesonrecomatrix) the other particle's color tag with the the color tag of 3rd particle collected to be baryon.
1699               for(int ijunc=0; ijunc < Tempjunctions.size(); ijunc++){
1700                 if((considering[0].col() == Tempjunctions.at(ijunc).at(1).at(1)) ||
1701                   (considering[0].col() == Tempjunctions.at(ijunc).at(2).at(1)) ||
1702                   (considering[0].col() == Tempjunctions.at(ijunc).at(3).at(1)) ) {
1703                   element1 = true;
1704                   juncnum1 = ijunc;
1705                 }
1706                 if((considering[1].col() == Tempjunctions.at(ijunc).at(1).at(1)) ||
1707                   (considering[1].col() == Tempjunctions.at(ijunc).at(2).at(1)) ||
1708                   (considering[1].col() == Tempjunctions.at(ijunc).at(3).at(1)) ) {
1709                   element2 = true;
1710                   juncnum2 = ijunc;
1711                 }
1712                 if((considering[2].col() == Tempjunctions.at(ijunc).at(1).at(1)) ||
1713                   (considering[2].col() == Tempjunctions.at(ijunc).at(2).at(1)) ||
1714                   (considering[2].col() == Tempjunctions.at(ijunc).at(3).at(1)) ) {
1715                   element3 = true;
1716                   juncnum3 = ijunc;
1717                 }
1718               }
1719               if((juncnum1 == juncnum2) && (juncnum1 != juncnum3) && juncnum1 != 999999999 && considering[2].col() != 0){
1720                 tagformatrix = Tempjunctions.at(juncnum1).at(3).at(1);
1721                 I2 = std::find(IndiceForColFin.begin(), IndiceForColFin.end(), considering[2].col());
1722                 loc2 = std::distance(IndiceForColFin.begin(), I2);
1723                 //std::cout <<endl<<"chosen color tag1 is "<<HH_showerptns[showerquarks[element[2]].par()].col();
1724                 //std::cout <<endl<<"and corresponding indice in the matrix is  "<<loc2<<endl;
1725               };
1726               if((juncnum2 == juncnum3) && (juncnum2 != juncnum1) && juncnum2 != 999999999 && considering[0].col() != 0){
1727                 tagformatrix = Tempjunctions.at(juncnum2).at(1).at(1);
1728                 I2 = std::find(IndiceForColFin.begin(), IndiceForColFin.end(), considering[0].col());
1729                 loc2 = std::distance(IndiceForColFin.begin(), I2);
1730                 //std::cout <<endl<<"chosen color tag2 is "<<HH_showerptns[showerquarks[element[0]].par()].col();
1731                 //std::cout <<endl<<"and corresponding indice in the matrix is  "<<loc2<<endl;
1732               };
1733               if((juncnum1 == juncnum3) && (juncnum1 != juncnum2) && juncnum3 != 999999999 && considering[1].col() != 0){
1734                 tagformatrix = Tempjunctions.at(juncnum3).at(2).at(1);
1735                 I2 = std::find(IndiceForColFin.begin(), IndiceForColFin.end(), considering[1].col());
1736                 loc2 = std::distance(IndiceForColFin.begin(), I2);
1737                 //std::cout <<endl<<"chosen color tag3 is "<<HH_showerptns[showerquarks[element[1]].par()].col();
1738                 //std::cout <<endl<<"and corresponding indice in the matrix is  "<<loc2<<endl;
1739               };
1740 
1741               I1 = std::find(IndiceForColFin.begin(), IndiceForColFin.end(), tagformatrix);
1742               loc1 = std::distance(IndiceForColFin.begin(), I1);
1743               //std::cout <<endl<<"chosen orginal color tag is "<<tagformatrix;
1744               //std::cout <<endl<<"and corresponding indice in the matrix is  "<<loc1<<endl;// now we find the locations of the color tags.
1745 
1746               //std::cout <<endl<<"loc2 is given as "<<loc2<<endl;
1747               // now, search the mesonrecomatrix
1748               if (tagformatrix < 999999999 && loc1 < standard && loc2 < standard) { // Not all the tags are in same junction so loc1,2 has always same or smaller value than the size of INdiceForColFin vector
1749                 if(MesonrecoMatrix1.at(loc1).at(loc2) == 1) {
1750                   recofactor3 = 1; // one specific tag, which is located in different location from other two strings from a junction, is neighbored with the tag in the not used tag in junction
1751                 }else{
1752                   recofactor3 = 1./9.;
1753                 } // general case
1754               }else{recofactor3 = 1./27.;} // general case
1755 
1756               if((juncnum1 == juncnum2) && (juncnum2 == juncnum3) && (tagformatrix != 999999999)){
1757                 recofactor3 = 1.;
1758               }
1759             }
1760             else if(considering[0].id()*considering[1].id()*considering[2].id() < 0){
1761 
1762               for(int ijunc=0; ijunc < Tempjunctions.size(); ijunc++){
1763                 if((considering[0].acol() == Tempjunctions.at(ijunc).at(1).at(1)) ||
1764                   (considering[0].acol() == Tempjunctions.at(ijunc).at(2).at(1)) ||
1765                   (considering[0].acol() == Tempjunctions.at(ijunc).at(3).at(1)) ) {
1766                   element1 = true;
1767                   juncnum1 = ijunc;
1768                 }
1769                 if((considering[1].acol() == Tempjunctions.at(ijunc).at(1).at(1)) ||
1770                   (considering[1].acol() == Tempjunctions.at(ijunc).at(2).at(1)) ||
1771                   (considering[1].acol() == Tempjunctions.at(ijunc).at(3).at(1)) ) {
1772                   element2 = true;
1773                   juncnum2 = ijunc;
1774                 }
1775                 if((considering[2].acol() == Tempjunctions.at(ijunc).at(1).at(1)) ||
1776                   (considering[2].acol() == Tempjunctions.at(ijunc).at(2).at(1)) ||
1777                   (considering[2].acol() == Tempjunctions.at(ijunc).at(3).at(1)) ) {
1778                   element3 = true;
1779                   juncnum3 = ijunc;
1780                 }
1781               }
1782               if((juncnum1 == juncnum2) && (juncnum1 != juncnum3) && juncnum1 != 999999999){
1783                 tagformatrix = Tempjunctions.at(juncnum1).at(3).at(1);
1784                 I2 = std::find(IndiceForColFin.begin(), IndiceForColFin.end(), considering[2].acol());
1785                 loc2 = std::distance(IndiceForColFin.begin(), I2);
1786                 //std::cout <<endl<<"chosen color tag1 is "<<HH_showerptns[showerquarks[element[2]].par()].col();
1787                 //std::cout <<endl<<"and corresponding indice in the matrix is  "<<loc2<<endl;
1788               };
1789               if((juncnum2 == juncnum3) && (juncnum2 != juncnum1) && juncnum2 != 999999999){
1790                 tagformatrix = Tempjunctions.at(juncnum2).at(1).at(1);
1791                 I2 = std::find(IndiceForColFin.begin(), IndiceForColFin.end(), considering[0].acol());
1792                 loc2 = std::distance(IndiceForColFin.begin(), I2);
1793                 //std::cout <<endl<<"chosen color tag2 is "<<HH_showerptns[showerquarks[element[0]].par()].col();
1794                 //std::cout <<endl<<"and corresponding indice in the matrix is  "<<loc2<<endl;
1795               };
1796               if((juncnum1 == juncnum3) && (juncnum1 != juncnum2) && juncnum3 != 999999999){
1797                 tagformatrix = Tempjunctions.at(juncnum3).at(2).at(1);
1798                 I2 = std::find(IndiceForColFin.begin(), IndiceForColFin.end(), considering[1].acol());
1799                 loc2 = std::distance(IndiceForColFin.begin(), I2);
1800                 //std::cout <<endl<<"chosen color tag3 is "<<HH_showerptns[showerquarks[element[1]].par()].col();
1801                 //std::cout <<endl<<"and corresponding indice in the matrix is  "<<loc2<<endl;
1802               };
1803 
1804               I1 = std::find(IndiceForColFin.begin(), IndiceForColFin.end(), tagformatrix);
1805               loc1 = std::distance(IndiceForColFin.begin(), I1);
1806               //std::cout <<endl<<"chosen orginal color tag is "<<tagformatrix;
1807               //std::cout <<endl<<"and corresponding indice in the matrix is  "<<loc1<<endl;// now we find the locations of the color tags.
1808 
1809               //std::cout <<endl<<"loc2 is given as "<<loc2<<endl;
1810               // now, search the mesonrecomatrix
1811               if (tagformatrix < 999999999 && loc1 < standard && loc2 < standard) { // Not all the tags are in same junction so loc1,2 has always same or smaller value than the size of INdiceForColFin vector
1812                 if(MesonrecoMatrix1.at(loc1).at(loc2) == 1) {
1813                   recofactor3 = 1; // one specific tag, which is located in different location from other two strings from a junction, is neighbored with the tag in the not used tag in junction
1814                 }else{
1815                   recofactor3 = 1./9.;
1816                 } // general case
1817               }
1818               else{recofactor3 = 1./27.;} // general case
1819 
1820               if((juncnum1 == juncnum2) && (juncnum2 == juncnum3) && (tagformatrix != 999999999)){
1821                 recofactor3 = 1.;
1822               }
1823             }
1824                     //recofactor3 = sh_recofactor*recofactor2;
1825                   }else if(perm2[q3]<0){
1826                     //skipping if the current quark cannot make a baryon with other two quarks
1827                     if(HH_thermal[-element[2]].id()*considering[0].id() < 0){continue;}
1828                     //skipping if current quark has been used
1829                     if(HH_thermal[-element[2]].status() != 0 || HH_thermal[-element[2]].is_used()){continue;}
1830                     //skipping if the current quark is from the same gluon as q2
1831                     else if((perm2[q2] < 0) && (HH_thermal[-element[1]].par() != -1) && (HH_thermal[-element[1]].par() == HH_thermal[-element[2]].par())){continue;}
1832                     //skipping if current quark is not a u,d,s,c,b quark
1833                     else if(std::abs(HH_thermal[-element[2]].id()) > 5){JSWARN << "SOMETHING OTHER THAN u,d,s,c,b WAS considered for recombination, THIS SHOULD NOT HAPPEN!"; continue;}
1834                     //turning off recombination for thermal partons in a computationally friendly way...
1835                     else if(th_recofactor < 0.001){continue;}
1836 
1837                     //checking distance cut ONLY if this is a thermal parton - skip if dist2 > dist2cut
1838                     FourVector pos_ptn1 = considering[0].pos(); FourVector pos_ptn2 = considering[1].pos(); FourVector pos_ptn3 = HH_thermal[-element[2]].pos();
1839                     if((pos_ptn1.t() > pos_ptn2.t()) && (pos_ptn1.t() > pos_ptn3.t())){
1840                         double dt_E2 = (pos_ptn1.t() - pos_ptn2.t())/considering[1].e(); double dt_E3 = (pos_ptn1.t() - pos_ptn3.t())/HH_thermal[-element[2]].e();
1841                         pos_ptn2.Set(pos_ptn2.x()+considering[1].px()*dt_E2,pos_ptn2.y()+considering[1].py()*dt_E2,pos_ptn2.z()+considering[1].pz()*dt_E2,0.);
1842                         pos_ptn3.Set(pos_ptn3.x()+HH_thermal[-element[2]].px()*dt_E3,pos_ptn3.y()+HH_thermal[-element[2]].py()*dt_E3,pos_ptn3.z()+HH_thermal[-element[2]].pz()*dt_E3,0.);
1843                     }
1844                     else if((pos_ptn2.t() > pos_ptn1.t()) && (pos_ptn2.t() > pos_ptn3.t())){
1845                         double dt_E1 = (pos_ptn2.t() - pos_ptn1.t())/considering[0].e(); double dt_E3 = (pos_ptn2.t() - pos_ptn3.t())/HH_thermal[-element[2]].e();
1846                         pos_ptn1.Set(pos_ptn1.x()+considering[0].px()*dt_E1,pos_ptn1.y()+considering[0].py()*dt_E1,pos_ptn1.z()+considering[0].pz()*dt_E1,0.);
1847                         pos_ptn3.Set(pos_ptn3.x()+HH_thermal[-element[2]].px()*dt_E3,pos_ptn3.y()+HH_thermal[-element[2]].py()*dt_E3,pos_ptn3.z()+HH_thermal[-element[2]].pz()*dt_E3,0.);
1848                     }
1849                     else{
1850                         double dt_E1 = (pos_ptn3.t() - pos_ptn1.t())/considering[0].e(); double dt_E2 = (pos_ptn3.t() - pos_ptn2.t())/considering[1].e();
1851                         pos_ptn1.Set(pos_ptn1.x()+considering[0].px()*dt_E1,pos_ptn1.y()+considering[0].py()*dt_E1,pos_ptn1.z()+considering[0].pz()*dt_E1,0.);
1852                         pos_ptn2.Set(pos_ptn2.x()+considering[1].px()*dt_E2,pos_ptn2.y()+considering[1].py()*dt_E2,pos_ptn2.z()+considering[1].pz()*dt_E2,0.);
1853                     }
1854                     if((dif2(pos_ptn3,pos_ptn1) > dist2cut) || (dif2(pos_ptn3,pos_ptn2) > dist2cut) || (dif2(pos_ptn1,pos_ptn2) > dist2cut)){continue;}
1855 
1856                     considering.add(HH_thermal[-element[2]]);
1857                     HH_thermal[-element[2]].status(-993);
1858                   }else{JSWARN << "SOMETHING WENT HORRIBLY WRONG - DO NOT KNOW WHERE CURRENT QUARK CAME FROM?!";}
1859 
1860                   //now that we *could* form a baryon, now we check if we actually do form one
1861                   //baryon momentum
1862                   FourVector Pbaryon;
1863                   Pbaryon.Set(considering[0].px()+considering[1].px()+considering[2].px(),considering[0].py()+considering[1].py()+considering[2].py(),considering[0].pz()+considering[1].pz()+considering[2].pz(),0.);
1864 
1865                   //baryon(CM) velocity
1866                   FourVector betaB; //really p[i]/e below
1867                   betaB.Set(Pbaryon.x()/(considering[0].e()+considering[1].e()+considering[2].e()),Pbaryon.y()/(considering[0].e()+considering[1].e()+considering[2].e()),Pbaryon.z()/(considering[0].e()+considering[1].e()+considering[2].e()),0.);
1868                   betaB.Set(betaB.x(),betaB.y(),betaB.z(),1./(sqrt(1. - (betaB.x()*betaB.x() + betaB.y()*betaB.y() + betaB.z()*betaB.z()))));
1869 
1870                   //boosting into CM frame
1871                   FourVector pos_BCM[3], p_BCM[3];
1872                   pos_BCM[0] = considering[0].boost_pos(betaB); pos_BCM[1] = considering[1].boost_pos(betaB); pos_BCM[2] = considering[2].boost_pos(betaB);
1873                     p_BCM[0] = considering[0].boost_P(betaB);     p_BCM[1] = considering[1].boost_P(betaB);     p_BCM[2] = considering[2].boost_P(betaB);
1874 
1875                   //velocities in CM frame
1876                   FourVector v_BCM[3];
1877                   v_BCM[0].Set(p_BCM[0].x()/p_BCM[0].t(),p_BCM[0].y()/p_BCM[0].t(),p_BCM[0].z()/p_BCM[0].t(),0.); //these are really p[i]/e
1878                   v_BCM[1].Set(p_BCM[1].x()/p_BCM[1].t(),p_BCM[1].y()/p_BCM[1].t(),p_BCM[1].z()/p_BCM[1].t(),0.);
1879                   v_BCM[2].Set(p_BCM[2].x()/p_BCM[2].t(),p_BCM[2].y()/p_BCM[2].t(),p_BCM[2].z()/p_BCM[2].t(),0.);
1880 
1881                   //propagating quarks until time of youngest quark
1882                   double curtime = std::max(std::max(pos_BCM[0].t(), pos_BCM[1].t()), pos_BCM[2].t());
1883                   FourVector cur_pos[3];
1884                   cur_pos[0].Set(pos_BCM[0].x()+v_BCM[0].x()*(curtime-pos_BCM[0].t()),pos_BCM[0].y()+v_BCM[0].y()*(curtime-pos_BCM[0].t()),pos_BCM[0].z()+v_BCM[0].z()*(curtime-pos_BCM[0].t()),curtime);
1885                   cur_pos[1].Set(pos_BCM[1].x()+v_BCM[1].x()*(curtime-pos_BCM[1].t()),pos_BCM[1].y()+v_BCM[1].y()*(curtime-pos_BCM[1].t()),pos_BCM[1].z()+v_BCM[1].z()*(curtime-pos_BCM[1].t()),curtime);
1886                   cur_pos[2].Set(pos_BCM[2].x()+v_BCM[2].x()*(curtime-pos_BCM[2].t()),pos_BCM[2].y()+v_BCM[2].y()*(curtime-pos_BCM[2].t()),pos_BCM[2].z()+v_BCM[2].z()*(curtime-pos_BCM[2].t()),curtime);
1887 
1888                   //finding position of CM at curtime
1889                   FourVector pos_CM;
1890                   pos_CM.Set(
1891                   (cur_pos[0].x()*considering[0].mass()+cur_pos[1].x()*considering[1].mass()+cur_pos[2].x()*considering[2].mass())/(considering[0].mass()+considering[1].mass()+considering[2].mass()),
1892                   (cur_pos[0].y()*considering[0].mass()+cur_pos[1].y()*considering[1].mass()+cur_pos[2].y()*considering[2].mass())/(considering[0].mass()+considering[1].mass()+considering[2].mass()),
1893                   (cur_pos[0].z()*considering[0].mass()+cur_pos[1].z()*considering[1].mass()+cur_pos[2].z()*considering[2].mass())/(considering[0].mass()+considering[1].mass()+considering[2].mass()),
1894                   curtime
1895                   );
1896 
1897                   //finding position of baryon in lab frame
1898                   betaB.Set(-betaB.x(),-betaB.y(),-betaB.z(),betaB.t());
1899                   FourVector pos_lab = HHboost(betaB, pos_CM);
1900 
1901                   //finding relative momenta of partons in CM frame
1902                   FourVector k_rel_square[2];
1903                   k_rel_square[0].Set(
1904                   (considering[1].mass()*p_BCM[0].x()-considering[0].mass()*p_BCM[1].x())/(considering[0].mass()+considering[1].mass()),
1905                   (considering[1].mass()*p_BCM[0].y()-considering[0].mass()*p_BCM[1].y())/(considering[0].mass()+considering[1].mass()),
1906                   (considering[1].mass()*p_BCM[0].z()-considering[0].mass()*p_BCM[1].z())/(considering[0].mass()+considering[1].mass()),
1907                   0.);
1908                   k_rel_square[1].Set(
1909                   (considering[2].mass()*(p_BCM[0].x()+p_BCM[1].x())-(considering[0].mass()+considering[1].mass())*p_BCM[2].x())/(considering[0].mass()+considering[1].mass()+considering[2].mass()),
1910                   (considering[2].mass()*(p_BCM[0].y()+p_BCM[1].y())-(considering[0].mass()+considering[1].mass())*p_BCM[2].y())/(considering[0].mass()+considering[1].mass()+considering[2].mass()),
1911                   (considering[2].mass()*(p_BCM[0].z()+p_BCM[1].z())-(considering[0].mass()+considering[1].mass())*p_BCM[2].z())/(considering[0].mass()+considering[1].mass()+considering[2].mass()),
1912                   0.);
1913 
1914                   //finding relative positions of partons in CM frame
1915                   FourVector pos_rel_square[2];
1916                   pos_rel_square[0].Set((cur_pos[0].x()-cur_pos[1].x()),(cur_pos[0].y()-cur_pos[1].y()),(cur_pos[0].z()-cur_pos[1].z()),0.);
1917                   pos_rel_square[1].Set(
1918                   ((cur_pos[0].x()*considering[0].mass()+cur_pos[1].x()*considering[1].mass())/(considering[0].mass()+considering[1].mass())-cur_pos[2].x()),
1919                   ((cur_pos[0].y()*considering[0].mass()+cur_pos[1].y()*considering[1].mass())/(considering[0].mass()+considering[1].mass())-cur_pos[2].y()),
1920                   ((cur_pos[0].z()*considering[0].mass()+cur_pos[1].z()*considering[1].mass())/(considering[0].mass()+considering[1].mass())-cur_pos[2].z()),
1921                   0.);
1922 
1923 
1924                   double SigRB2 = SigNucR2; double SigLB2 = SigNucL2;
1925                   int sortid[3] = {std::abs(considering[0].id()),std::abs(considering[1].id()),std::abs(considering[2].id())};
1926                   std::stable_sort(std::begin(sortid), std::end(sortid), std::greater<int>());
1927 
1928                   //for particles we don't want to form, setting recofactor3 to 0
1929                   if(     sortid[0] == 3){
1930                     if(     sortid[1] == 3){
1931                         if(     sortid[2] == 3){SigRB2 = SigOmgR2;  SigLB2 = SigOmgL2;}
1932                         else{                   SigRB2 = SigXiR2;   SigLB2 = SigXiL2;}
1933                     }
1934                     else{                       SigRB2 = SigSigR2;  SigLB2 = SigSigL2;}
1935                   }
1936                   else if(sortid[0] == 4){
1937                     if(     sortid[1] == 4){
1938                         if(     sortid[2] == 4){SigRB2 = SigOcccR2; SigLB2 = SigOcccL2;}
1939                         else if(sortid[2] == 3){SigRB2 = SigOccR2;  SigLB2 = SigOccL2;}
1940                         else{                   SigRB2 = SigXiccR2; SigLB2 = SigXiccL2;}
1941                     }
1942                     else if(sortid[1] == 3){
1943                         if(     sortid[2] == 3){SigRB2 = SigOcR2;   SigLB2 = SigOcL2;}
1944                         else{                   SigRB2 = SigXicR2;  SigLB2 = SigXicL2;}
1945                     }
1946                     else{                       SigRB2 = SigSigcR2; SigLB2 = SigSigcL2;}
1947                   }
1948                   else if(sortid[0] == 5){
1949                     if(     sortid[1] == 5){
1950                         if(     sortid[2] == 5){SigRB2 = SigObbbR2; SigLB2 = SigObbbL2; recofactor3=0.;}
1951                         else if(sortid[2] == 4){SigRB2 = SigObbcR2; SigLB2 = SigObbcL2; recofactor3=0.;}
1952                         else if(sortid[2] == 3){SigRB2 = SigObbR2;  SigLB2 = SigObbL2;  recofactor3=0.;}
1953                         else{                   SigRB2 = SigXibbR2; SigLB2 = SigXibbL2; recofactor3=0.;}
1954                     }
1955                     else if(sortid[1] == 4){
1956                         if(     sortid[2] == 4){SigRB2 = SigObccR2; SigLB2 = SigObccL2; recofactor3=0.;}
1957                         else if(sortid[2] == 3){SigRB2 = SigObcR2;  SigLB2 = SigObcL2;  recofactor3=0.;}
1958                         else{                   SigRB2 = SigXibcR2; SigLB2 = SigXibcL2; recofactor3=0.;}
1959                     }
1960                     else if(sortid[1] == 3){
1961                         if(     sortid[2] == 3){SigRB2 = SigObR2;   SigLB2 = SigObL2;}
1962                         else{                   SigRB2 = SigXibR2;  SigLB2 = SigXibL2;}
1963                     }
1964                     else{                       SigRB2 = SigSigbR2; SigLB2 = SigSigbL2;}
1965                   }
1966 
1967                   //precalc's for Wigner Wavefunction
1968                   //0:x, 1:y, 2:z ::: urho:(rel. between partons 1,2), ulamb:(rel. between partons (1,2),3)
1969                   double urho[3], ulamb[3];
1970                   urho[0] =  0.5*(pos_rel_square[0].x()*pos_rel_square[0].x()/SigRB2 + k_rel_square[0].x()*k_rel_square[0].x()*SigRB2/hbarc2);
1971                   urho[1] =  0.5*(pos_rel_square[0].y()*pos_rel_square[0].y()/SigRB2 + k_rel_square[0].y()*k_rel_square[0].y()*SigRB2/hbarc2);
1972                   urho[2] =  0.5*(pos_rel_square[0].z()*pos_rel_square[0].z()/SigRB2 + k_rel_square[0].z()*k_rel_square[0].z()*SigRB2/hbarc2);
1973                   ulamb[0] = 0.5*(pos_rel_square[1].x()*pos_rel_square[1].x()/SigLB2 + k_rel_square[1].x()*k_rel_square[1].x()*SigLB2/hbarc2);
1974                   ulamb[1] = 0.5*(pos_rel_square[1].y()*pos_rel_square[1].y()/SigLB2 + k_rel_square[1].y()*k_rel_square[1].y()*SigLB2/hbarc2);
1975                   ulamb[2] = 0.5*(pos_rel_square[1].z()*pos_rel_square[1].z()/SigLB2 + k_rel_square[1].z()*k_rel_square[1].z()*SigLB2/hbarc2);
1976 
1977                   //1D GS Wig. wavefunction
1978                   double wig0[2][3];
1979                   wig0[0][0] = std::exp(-urho[0]);  wig0[0][1] = std::exp(-urho[1]);  wig0[0][2] = std::exp(-urho[2]);
1980                   wig0[1][0] = std::exp(-ulamb[0]); wig0[1][1] = std::exp(-ulamb[1]); wig0[1][2] = std::exp(-ulamb[2]);
1981                   //3D GS Wig. wavefunction
1982                   double WigB[2];
1983                   WigB[0] = wig0[0][0]*wig0[0][1]*wig0[0][2]*wig0[1][0]*wig0[1][1]*wig0[1][2];
1984 
1985                   //summing up 3D Wig. wavefunctions over nlev excited states
1986                   WigB[1] = 0.; //sumWigB;
1987 
1988                   double wigE[2][3];
1989                   for(int i=0;i<2;++i){for(int j=0;j<2;++j){wigE[i][j]=0.;}}
1990 
1991                   wigE[0][0] = wig0[0][0];
1992                   for(int iRx=0; iRx<=maxB_level; ++iRx){
1993                     wigE[0][1] = wig0[0][1];
1994                     for(int iRy=0; iRy<=maxB_level-iRx; ++iRy){
1995                         wigE[0][2] = wig0[0][2];
1996                         for(int iRz=0; iRz<=maxB_level-iRx-iRy; ++iRz){
1997                             wigE[1][0] = wig0[1][0];
1998                             for(int iLx=0; iLx<=maxB_level-iRx-iRy-iRz; ++iLx){
1999                                 wigE[1][1] = wig0[1][1];
2000                                 for(int iLy=0; iLy<=maxB_level-iRx-iRy-iRz-iLx; ++iLy){
2001                                     wigE[1][2] = wig0[1][2];
2002                                     for(int iLz=0; iLz<=maxB_level-iRx-iRy-iRz-iLx-iLy; ++iLz){
2003                                         WigB[1] += wigE[0][0]*wigE[0][1]*wigE[0][2]*wigE[1][0]*wigE[1][1]*wigE[1][2];
2004                                         wigE[1][2] *= ulamb[2]/((double(iLz))+1.);
2005                                     }
2006                                     wigE[1][1] *= ulamb[1]/((double(iLy))+1.);
2007                                 }
2008                                 wigE[1][0] *= ulamb[0]/((double(iLx))+1.);
2009                             }
2010                             wigE[0][2] *= urho[2]/((double(iRz))+1.);
2011                         }
2012                         wigE[0][1] *= urho[1]/((double(iRy))+1.);
2013                     }
2014                     wigE[0][0] *= urho[0]/((double(iRx))+1.);
2015                   }
2016 
2017           if(maxB_level == -1) {
2018             WigB[0] = 0.;
2019             WigB[1] = 0.;
2020           }
2021 
2022                   //Checking if baryon is formed (either ground or excited state)
2023                   double rndbaryon = ran();
2024                 double mult = (considering[1].is_thermal() || considering[2].is_thermal()) ? th_recofactor : sh_recofactor;
2025                 if(WigB[1]*recofactor3*mult >= rndbaryon){
2026             int junction_with_thermal_parton = 0;
2027 
2028             /*std::cout << "Baryons" << std::endl;
2029             std::cout << considering[0].id() << "," << considering[0].col() << "," << considering[0].acol() << std::endl;
2030             std::cout << considering[1].id() << "," << considering[1].col() << "," << considering[1].acol() << std::endl;
2031             std::cout << considering[2].id() << "," << considering[2].col() << "," << considering[2].acol() << std::endl;*/
2032                   if(considering[0].id() * considering[1].id() * considering[2].id() > 0){
2033               // baryon is to be formed, so temporary anti junction is defined
2034               if(considering[0].col() > 0 && considering[1].col() > 0 && considering[2].col() > 0) {
2035                 IdColInfo1.push_back(-1); // antijunction tag(-1)
2036                 IdColInfo1.push_back(junction_with_thermal_parton);
2037                 IdColInfo2.push_back(-1); // means anticolor tag(negative color charge)
2038                 IdColInfo2.push_back(considering[0].col());// {-1, anticolor tag} will be at 2nd, 3rd, 4th
2039                 IdColInfo3.push_back(-1);
2040                 IdColInfo3.push_back(considering[1].col());
2041                 IdColInfo4.push_back(-1);
2042                 IdColInfo4.push_back(considering[2].col());
2043 
2044                 JunctionInfo.push_back(IdColInfo1);
2045                 JunctionInfo.push_back(IdColInfo2);
2046                 JunctionInfo.push_back(IdColInfo3);
2047                 JunctionInfo.push_back(IdColInfo4);
2048 
2049                 Tempjunctions.push_back(JunctionInfo); // information of tempjunction is saved so et clear subordinate vector for next entry
2050 
2051                 IdColInfo1.clear();
2052                 IdColInfo2.clear();
2053                 IdColInfo3.clear();
2054                 IdColInfo4.clear();
2055                 JunctionInfo.clear();
2056 
2057                 //Since Baryon is formed, color tag for neutrality should be added, casting int into double is needed!!(ex (double) intvalue
2058                 int coltag1 = considering[0].col();
2059                 int coltag2 = considering[1].col();
2060                 int coltag3 = considering[2].col();
2061                 if(coltag1 > 0 && coltag2 > 0 && coltag3 > 0 && coltag1 <= limit && coltag2 <= limit && coltag3 <= limit ){
2062                   double tag1 = (double)coltag1;  // they are casted to be inserted into the matrix(since it's vector of double
2063                   double tag2 = (double)coltag2;
2064                   double tag3 = (double)coltag3;
2065                   std::vector<int>::iterator I1 = std::find(IndiceForColFin.begin(), IndiceForColFin.end(), coltag1);
2066                   std::vector<int>::iterator I2 = std::find(IndiceForColFin.begin(), IndiceForColFin.end(), coltag2);
2067                   std::vector<int>::iterator I3 = std::find(IndiceForColFin.begin(), IndiceForColFin.end(), coltag3);
2068                   int loc1 = std::distance(IndiceForColFin.begin(), I1);
2069                   int loc2 = std::distance(IndiceForColFin.begin(), I2);
2070                   int loc3 = std::distance(IndiceForColFin.begin(), I3); //set up for find matrix indices corresponding to the color tags (we just found the corresponding indice in BaryonrecoMatrix1 with col tags )
2071 
2072                   BaryonrecoMatrix1.at(loc1).at(loc2).at(1) = tag3;
2073                   BaryonrecoMatrix1.at(loc2).at(loc1).at(1) = tag3;
2074                   BaryonrecoMatrix1.at(loc2).at(loc3).at(1) = tag1;
2075                   BaryonrecoMatrix1.at(loc3).at(loc2).at(1) = tag1;
2076                   BaryonrecoMatrix1.at(loc1).at(loc3).at(1) = tag2;
2077                   BaryonrecoMatrix1.at(loc3).at(loc1).at(1) = tag2; // now the color tag info for color neutrality is saved in Matrix, also we need to consider the impact from this to Meson Formation
2078 
2079                   //MesonrecoMatrix1 is modified by below
2080                   MesonrecoMatrix1.at(loc1).at(loc2) = 0;
2081                   MesonrecoMatrix1.at(loc2).at(loc1) = 0;
2082                   MesonrecoMatrix1.at(loc2).at(loc3) = 0;
2083                   MesonrecoMatrix1.at(loc3).at(loc2) = 0;
2084                   MesonrecoMatrix1.at(loc1).at(loc3) = 0;
2085                   MesonrecoMatrix1.at(loc3).at(loc1) = 0; // since three color tags of baryon are different from each other, so that these tags can't form meson with each other.
2086                 }
2087                 /*
2088                 //dignostic measure
2089                 std::cout <<endl<<"Meson reco Matrix revised by Baryon formation is same as below"<<endl;
2090                 for(int irow=0; irow < IndiceForColFin.size(); irow++){
2091                   for(int icol=0; icol < IndiceForColFin.size(); icol++){
2092                     std::cout <<"  "<<MesonrecoMatrix1.at(irow).at(icol)<<"  ";
2093                   }
2094                   std::cout <<endl<<endl;
2095                 }
2096                 //dignostic measure
2097                 std::cout <<endl<<"Revised Baryon reco Matrix is same as below"<<endl;
2098                 for(int irow=0; irow < IndiceForColFin.size(); irow++){
2099                   for(int icol=0; icol < IndiceForColFin.size(); icol++){
2100                     std::cout <<"  ( "<<BaryonrecoMatrix1.at(irow).at(icol).at(1)<<" )  ";
2101                   }
2102                   std::cout <<endl<<endl;
2103                 }
2104                 */
2105               }
2106               if(considering[0].col() > 0 && considering[1].col() == 0 && considering[2].col() > 0){ // MAT + Therm/LBT + MAT case
2107                 IdColInfo1.push_back(-1); // antijunction tag(-1)
2108 
2109                 maxtag++;
2110                 int loc = findcloserepl(considering[1], perm2[q2], true, true, showerquarks, HH_thermal);
2111                 if(loc == 999999999){
2112                   //std::cout <<endl<<"Warning : extra parton used for string repair!!"<<endl;
2113                   HHparton fakep = considering[1]; fakep.id(-fakep.id());  fakep.acol(maxtag);
2114                   fakep.mass(pythia.particleData.m0(std::abs(fakep.id())));
2115                   fakep.px(0.); fakep.py(0.); fakep.pz(0.);
2116                   fakep.e(fakep.mass());
2117                   fakep.is_fakeparton(true);
2118                   Extraparton.add(fakep);
2119                   junction_with_thermal_parton = 1;
2120                   //somewhere, we need to make for loop to toss all partons to remnants list.
2121                 }
2122                 else if (loc > 0){showerquarks[loc - 1].acol(maxtag); }
2123                 else if(loc < 0){HH_thermal[-loc - 1].acol(maxtag); junction_with_thermal_parton = 1;}
2124 
2125                 IdColInfo1.push_back(junction_with_thermal_parton);
2126 
2127                 //TODO: give thermal partons "ANTI COLOR TAGS" to form anti junction and conserve baryon number.
2128                 IdColInfo2.push_back(-1); // means anticolor tag(negative color charge)
2129                 IdColInfo2.push_back(considering[0].col());// {-1, anticolor tag} will be at 2nd, 3rd, 4th
2130                 IdColInfo3.push_back(-1);
2131                 IdColInfo3.push_back(maxtag);
2132                 IdColInfo4.push_back(-1);
2133                 IdColInfo4.push_back(considering[2].col());
2134 
2135                 JunctionInfo.push_back(IdColInfo1);
2136                 JunctionInfo.push_back(IdColInfo2);
2137                 JunctionInfo.push_back(IdColInfo3);
2138                 JunctionInfo.push_back(IdColInfo4);
2139 
2140                 Tempjunctions.push_back(JunctionInfo); // information of tempjunction is saved so et clear subordinate vector for next entry
2141 
2142                 IdColInfo1.clear();
2143                 IdColInfo2.clear();
2144                 IdColInfo3.clear();
2145                 IdColInfo4.clear();
2146                 JunctionInfo.clear();
2147               }
2148               if(considering[0].col() == 0 && considering[1].col() > 0 && considering[2].col() > 0){ // LBT + MAT + MAT case
2149                 IdColInfo1.push_back(-1); // antijunction tag(-1)
2150 
2151                 maxtag++;
2152                 int loc = findcloserepl(considering[0], element[0] + 1, true, true, showerquarks, HH_thermal);
2153                 if(loc == 999999999){
2154                   //std::cout <<endl<<"Warning : extra parton used for string repair!!"<<endl;
2155                   HHparton fakep = considering[0]; fakep.id(-fakep.id());  fakep.acol(maxtag);
2156                   fakep.mass(pythia.particleData.m0(std::abs(fakep.id())));
2157                   fakep.px(0.); fakep.py(0.); fakep.pz(0.);
2158                   fakep.e(fakep.mass());
2159                   fakep.is_fakeparton(true);
2160                   Extraparton.add(fakep);
2161                   junction_with_thermal_parton = 1;
2162                   //somewhere, we need to make for loop to toss all partons to remnants list.
2163                 }
2164                 else if (loc > 0){showerquarks[loc - 1].acol(maxtag); }
2165                 else if(loc < 0){HH_thermal[-loc - 1].acol(maxtag); junction_with_thermal_parton = 1;}
2166 
2167                 IdColInfo1.push_back(junction_with_thermal_parton);
2168 
2169                 IdColInfo2.push_back(-1); // means anticolor tag(negative color charge)
2170                 IdColInfo2.push_back(maxtag);// {-1, anticolor tag} will be at 2nd, 3rd, 4th
2171                 IdColInfo3.push_back(-1);
2172                 IdColInfo3.push_back(considering[1].col());
2173                 IdColInfo4.push_back(-1);
2174                 IdColInfo4.push_back(considering[2].col());
2175 
2176                 JunctionInfo.push_back(IdColInfo1);
2177                 JunctionInfo.push_back(IdColInfo2);
2178                 JunctionInfo.push_back(IdColInfo3);
2179                 JunctionInfo.push_back(IdColInfo4);
2180 
2181                 Tempjunctions.push_back(JunctionInfo); // information of tempjunction is saved so et clear subordinate vector for next entry
2182 
2183                 IdColInfo1.clear();
2184                 IdColInfo2.clear();
2185                 IdColInfo3.clear();
2186                 IdColInfo4.clear();
2187                 JunctionInfo.clear();
2188               }
2189               if(considering[0].col() > 0 && considering[1].col() > 0 && considering[2].col() == 0){ // MAT + MAT + Therm/LBT case
2190                 IdColInfo1.push_back(-1); // antijunction tag(-1)
2191 
2192                 maxtag++;
2193                 int loc = findcloserepl(considering[2], perm2[q3], true, true, showerquarks, HH_thermal);
2194                 if(loc == 999999999){
2195                   //std::cout <<endl<<"Warning : extra parton used for string repair!!"<<endl;
2196                   HHparton fakep = considering[1]; fakep.id(-fakep.id());  fakep.acol(maxtag);
2197                   fakep.mass(pythia.particleData.m0(std::abs(fakep.id())));
2198                   fakep.px(0.); fakep.py(0.); fakep.pz(0.);
2199                   fakep.e(fakep.mass());
2200                   fakep.is_fakeparton(true);
2201                   Extraparton.add(fakep);
2202                   junction_with_thermal_parton = 1;
2203                   //somewhere, we need to make for loop to toss all partons to remnants list.
2204                 }
2205                 else if (loc > 0){showerquarks[loc - 1].acol(maxtag); }
2206                 else if(loc < 0){HH_thermal[-loc - 1].acol(maxtag); junction_with_thermal_parton = 1;}
2207 
2208                 IdColInfo1.push_back(junction_with_thermal_parton);
2209 
2210                 IdColInfo2.push_back(-1); // means anticolor tag(negative color charge)
2211                 IdColInfo2.push_back(considering[0].col());// {-1, anticolor tag} will be at 2nd, 3rd, 4th
2212                 IdColInfo3.push_back(-1);
2213                 IdColInfo3.push_back(considering[1].col());
2214                 IdColInfo4.push_back(-1);
2215                 IdColInfo4.push_back(maxtag);
2216 
2217                 JunctionInfo.push_back(IdColInfo1);
2218                 JunctionInfo.push_back(IdColInfo2);
2219                 JunctionInfo.push_back(IdColInfo3);
2220                 JunctionInfo.push_back(IdColInfo4);
2221 
2222                 Tempjunctions.push_back(JunctionInfo); // information of tempjunction is saved so et clear subordinate vector for next entry
2223 
2224                 IdColInfo1.clear();
2225                 IdColInfo2.clear();
2226                 IdColInfo3.clear();
2227                 IdColInfo4.clear();
2228                 JunctionInfo.clear();
2229               } // so far, we are finished with the list with one zero component.
2230               if(considering[0].col() > 0 && considering[1].col() == 0 && considering[2].col() == 0){ // MAT + Therm/LBT + Therm/LBT case
2231                 IdColInfo1.push_back(-1); // antijunction tag(-1)
2232                 IdColInfo2.push_back(-1); // means anticolor tag(negative color charge)
2233                 IdColInfo2.push_back(considering[0].col());// {-1, anticolor tag} will be at 2nd, 3rd, 4th
2234 
2235                 maxtag++;
2236                 int loc1 = findcloserepl(considering[1], perm2[q2], true, true, showerquarks, HH_thermal);
2237                 if(loc1 == 999999999){
2238                   //std::cout <<endl<<"Warning : extra parton used for string repair!!"<<endl;
2239                   HHparton fakep = considering[1]; fakep.id(-fakep.id());  fakep.acol(maxtag);
2240                   fakep.mass(pythia.particleData.m0(std::abs(fakep.id())));
2241                   fakep.px(0.); fakep.py(0.); fakep.pz(0.);
2242                   fakep.e(fakep.mass());
2243                   fakep.is_fakeparton(true);
2244                   Extraparton.add(fakep);
2245                   junction_with_thermal_parton = 1;
2246                   //somewhere, we need to make for loop to toss all partons to remnants list.
2247                 }
2248                 else if (loc1 > 0){showerquarks[loc1 - 1].acol(maxtag); }
2249                 else if(loc1 < 0){HH_thermal[-loc1 - 1].acol(maxtag); junction_with_thermal_parton = 1;}
2250                 IdColInfo3.push_back(-1);
2251                 IdColInfo3.push_back(maxtag);
2252 
2253                 maxtag++;
2254                 int loc2 = findcloserepl(considering[2], perm2[q3], true, true, showerquarks, HH_thermal);
2255                 if(loc2 == 999999999){
2256                   //std::cout <<endl<<"Warning : extra parton used for string repair!!"<<endl;
2257                   HHparton fakep = considering[1]; fakep.id(-fakep.id());  fakep.acol(maxtag);
2258                   fakep.mass(pythia.particleData.m0(std::abs(fakep.id())));
2259                   fakep.px(0.); fakep.py(0.); fakep.pz(0.);
2260                   fakep.e(fakep.mass());
2261                   fakep.is_fakeparton(true);
2262                   Extraparton.add(fakep);
2263                   junction_with_thermal_parton = 1;
2264                   //somewhere, we need to make for loop to toss all partons to remnants list.
2265                 }
2266                 else if (loc2 > 0){showerquarks[loc2 - 1].acol(maxtag); }
2267                 else if(loc2 < 0){HH_thermal[-loc2 - 1].acol(maxtag); junction_with_thermal_parton = 1;}
2268 
2269                 IdColInfo1.push_back(junction_with_thermal_parton);
2270 
2271                 IdColInfo4.push_back(-1);
2272                 IdColInfo4.push_back(maxtag);
2273                 //TODO: give thermal partons "ANTI COLOR TAGS" to form anti junction and conserve baryon number.
2274 
2275                 JunctionInfo.push_back(IdColInfo1);
2276                 JunctionInfo.push_back(IdColInfo2);
2277                 JunctionInfo.push_back(IdColInfo3);
2278                 JunctionInfo.push_back(IdColInfo4);
2279 
2280                 Tempjunctions.push_back(JunctionInfo); // information of tempjunction is saved so et clear subordinate vector for next entry
2281 
2282                 IdColInfo1.clear();
2283                 IdColInfo2.clear();
2284                 IdColInfo3.clear();
2285                 IdColInfo4.clear();
2286                 JunctionInfo.clear();
2287               }
2288               if(considering[0].col() == 0 && considering[1].col() == 0 && considering[2].col() > 0){ // Therm/LBT + Therm/LBT + MAT case
2289                 IdColInfo1.push_back(-1); // antijunction tag(-1)
2290 
2291                 maxtag++;
2292                 int loc1 = findcloserepl(considering[0], element[0] + 1, true, true, showerquarks, HH_thermal);
2293                 if(loc1 == 999999999){
2294                   //std::cout <<endl<<"Warning : extra parton used for string repair!!"<<endl;
2295                   HHparton fakep = considering[0]; fakep.id(-fakep.id());  fakep.acol(maxtag);
2296                   fakep.mass(pythia.particleData.m0(std::abs(fakep.id())));
2297                   fakep.px(0.); fakep.py(0.); fakep.pz(0.);
2298                   fakep.e(fakep.mass());
2299                   fakep.is_fakeparton(true);
2300                   Extraparton.add(fakep);
2301                   junction_with_thermal_parton = 1;
2302                   //somewhere, we need to make for loop to toss all partons to remnants list.
2303                 }
2304                 else if (loc1 > 0){showerquarks[loc1 - 1].acol(maxtag); }
2305                 else if(loc1 < 0){HH_thermal[-loc1 - 1].acol(maxtag); junction_with_thermal_parton = 1;}
2306                 IdColInfo3.push_back(-1);
2307                 IdColInfo3.push_back(maxtag);
2308 
2309                 maxtag++;
2310                 int loc2 = findcloserepl(considering[1], perm2[q2], true, true, showerquarks, HH_thermal);
2311                 if(loc2 == 999999999){
2312                   //std::cout <<endl<<"Warning : extra parton used for string repair!!"<<endl;
2313                   HHparton fakep = considering[1]; fakep.id(-fakep.id());  fakep.acol(maxtag);
2314                   fakep.mass(pythia.particleData.m0(std::abs(fakep.id())));
2315                   fakep.px(0.); fakep.py(0.); fakep.pz(0.);
2316                   fakep.e(fakep.mass());
2317                   fakep.is_fakeparton(true);
2318                   Extraparton.add(fakep);
2319                   junction_with_thermal_parton = 1;
2320                   //somewhere, we need to make for loop to toss all partons to remnants list.
2321                 }
2322                 else if (loc2 > 0){showerquarks[loc2 - 1].acol(maxtag); }
2323                 else if(loc2 < 0){HH_thermal[-loc2 - 1].acol(maxtag); junction_with_thermal_parton = 1;}
2324 
2325                 IdColInfo1.push_back(junction_with_thermal_parton);
2326 
2327                 IdColInfo4.push_back(-1);
2328                 IdColInfo4.push_back(maxtag);
2329                 //TODO: give thermal partons "ANTI COLOR TAGS" to form anti junction and conserve baryon number.
2330 
2331                 IdColInfo2.push_back(-1); // means anticolor tag(negative color charge)
2332                 IdColInfo2.push_back(considering[2].col());// {-1, anticolor tag} will be at 2nd, 3rd, 4th
2333 
2334                 JunctionInfo.push_back(IdColInfo1);
2335                 JunctionInfo.push_back(IdColInfo2);
2336                 JunctionInfo.push_back(IdColInfo3);
2337                 JunctionInfo.push_back(IdColInfo4);
2338 
2339                 Tempjunctions.push_back(JunctionInfo); // information of tempjunction is saved so et clear subordinate vector for next entry
2340 
2341                 IdColInfo1.clear();
2342                 IdColInfo2.clear();
2343                 IdColInfo3.clear();
2344                 IdColInfo4.clear();
2345                 JunctionInfo.clear();
2346               }
2347               if(considering[0].col() == 0 && considering[1].col() > 0 && considering[2].col() == 0){ // Therm/LBT + Therm/LBT + MAT case
2348                 IdColInfo1.push_back(-1); // antijunction tag(-1)
2349 
2350                 maxtag++;
2351                 int loc1 = findcloserepl(considering[0], element[0] + 1, true, true, showerquarks, HH_thermal);
2352                 if(loc1 == 999999999){
2353                   //std::cout <<endl<<"Warning : extra parton used for string repair!!"<<endl;
2354                   HHparton fakep = considering[0]; fakep.id(-fakep.id());  fakep.acol(maxtag);
2355                   fakep.mass(pythia.particleData.m0(std::abs(fakep.id())));
2356                   fakep.px(0.); fakep.py(0.); fakep.pz(0.);
2357                   fakep.e(fakep.mass());
2358                   fakep.is_fakeparton(true);
2359                   Extraparton.add(fakep);
2360                   junction_with_thermal_parton = 1;
2361                   //somewhere, we need to make for loop to toss all partons to remnants list.
2362                 }
2363                 else if (loc1 > 0){showerquarks[loc1 - 1].acol(maxtag); }
2364                 else if(loc1 < 0){HH_thermal[-loc1 - 1].acol(maxtag); junction_with_thermal_parton = 1;}
2365                 IdColInfo2.push_back(-1);
2366                 IdColInfo2.push_back(maxtag);
2367 
2368                 IdColInfo3.push_back(-1); // means anticolor tag(negative color charge)
2369                 IdColInfo3.push_back(considering[1].col());// {-1, anticolor tag} will be at 2nd, 3rd, 4th
2370 
2371                 maxtag++;
2372                 int loc2 = findcloserepl(considering[2], perm2[q3], true, true, showerquarks, HH_thermal);
2373                 if(loc2 == 999999999){
2374                   //std::cout <<endl<<"Warning : extra parton used for string repair!!"<<endl;
2375                   HHparton fakep = considering[2]; fakep.id(-fakep.id());  fakep.acol(maxtag);
2376                   fakep.mass(pythia.particleData.m0(std::abs(fakep.id())));
2377                   fakep.px(0.); fakep.py(0.); fakep.pz(0.);
2378                   fakep.e(fakep.mass());
2379                   fakep.is_fakeparton(true);
2380                   Extraparton.add(fakep);
2381                   junction_with_thermal_parton = 1;
2382                   //somewhere, we need to make for loop to toss all partons to remnants list.
2383                 }
2384                 else if (loc2 > 0){showerquarks[loc2 - 1].acol(maxtag); }
2385                 else if(loc2 < 0){HH_thermal[-loc2 - 1].acol(maxtag); junction_with_thermal_parton = 1;}
2386 
2387                 IdColInfo1.push_back(junction_with_thermal_parton);
2388 
2389                 IdColInfo4.push_back(-1);
2390                 IdColInfo4.push_back(maxtag);
2391 
2392                 JunctionInfo.push_back(IdColInfo1);
2393                 JunctionInfo.push_back(IdColInfo2);
2394                 JunctionInfo.push_back(IdColInfo3);
2395                 JunctionInfo.push_back(IdColInfo4);
2396 
2397                 Tempjunctions.push_back(JunctionInfo); // information of tempjunction is saved so et clear subordinate vector for next entry
2398 
2399                 IdColInfo1.clear();
2400                 IdColInfo2.clear();
2401                 IdColInfo3.clear();
2402                 IdColInfo4.clear();
2403                 JunctionInfo.clear();
2404               } // so far, we are finished with the list with two zeros
2405               if(considering[0].col() == 0 && considering[1].col() == 0 && considering[2].col() == 0){ // Therm/LBT + Therm/LBT + Therm/LBT
2406                 IdColInfo1.push_back(-1); // antijunction tag(-1)
2407 
2408                 maxtag++;
2409                 int loc1 = findcloserepl(considering[0], element[0] + 1, true, true, showerquarks, HH_thermal);
2410                 if(loc1 == 999999999){
2411                   //std::cout <<endl<<"Warning : extra parton used for string repair!!"<<endl;
2412                   HHparton fakep = considering[0]; fakep.id(-fakep.id());  fakep.acol(maxtag);
2413                   fakep.mass(pythia.particleData.m0(std::abs(fakep.id())));
2414                   fakep.px(0.); fakep.py(0.); fakep.pz(0.);
2415                   fakep.e(fakep.mass());
2416                   fakep.is_fakeparton(true);
2417                   Extraparton.add(fakep);
2418                   junction_with_thermal_parton = 1;
2419                   //somewhere, we need to make for loop to toss all partons to remnants list.
2420                 }
2421                 else if (loc1 > 0){showerquarks[loc1 - 1].acol(maxtag); }
2422                 else if(loc1 < 0){HH_thermal[-loc1 - 1].acol(maxtag); junction_with_thermal_parton = 1;}
2423                 IdColInfo2.push_back(-1);
2424                 IdColInfo2.push_back(maxtag);
2425 
2426                 maxtag++;
2427                 int loc2 = findcloserepl(considering[1], perm2[q2], true, true, showerquarks, HH_thermal);
2428                 if(loc2 == 999999999){
2429                   //std::cout <<endl<<"Warning : extra parton used for string repair!!"<<endl;
2430                   HHparton fakep = considering[1]; fakep.id(-fakep.id());  fakep.acol(maxtag);
2431                   fakep.mass(pythia.particleData.m0(std::abs(fakep.id())));
2432                   fakep.px(0.); fakep.py(0.); fakep.pz(0.);
2433                   fakep.e(fakep.mass());
2434                   fakep.is_fakeparton(true);
2435                   Extraparton.add(fakep);
2436                   junction_with_thermal_parton = 1;
2437                   //somewhere, we need to make for loop to toss all partons to remnants list.
2438                 }
2439                 else if (loc2 > 0){showerquarks[loc2 - 1].acol(maxtag); }
2440                 else if(loc2 < 0){HH_thermal[-loc2 - 1].acol(maxtag); junction_with_thermal_parton = 1;}
2441                 IdColInfo3.push_back(-1);
2442                 IdColInfo3.push_back(maxtag);
2443 
2444                 maxtag++;
2445                 int loc3 = findcloserepl(considering[2], perm2[q3], true, true, showerquarks, HH_thermal);
2446                 if(loc3 == 999999999){
2447                   //std::cout <<endl<<"Warning : extra parton used for string repair!!"<<endl;
2448                   HHparton fakep = considering[2]; fakep.id(-fakep.id());  fakep.acol(maxtag);
2449                   fakep.mass(pythia.particleData.m0(std::abs(fakep.id())));
2450                   fakep.px(0.); fakep.py(0.); fakep.pz(0.);
2451                   fakep.e(fakep.mass());
2452                   fakep.is_fakeparton(true);
2453                   Extraparton.add(fakep);
2454                   junction_with_thermal_parton = 1;
2455                   //somewhere, we need to make for loop to toss all partons to remnants list.
2456                 }
2457                 else if (loc3 > 0){showerquarks[loc3 - 1].acol(maxtag); }
2458                 else if(loc3 < 0){HH_thermal[-loc3 - 1].acol(maxtag); junction_with_thermal_parton = 1;}
2459 
2460                 IdColInfo1.push_back(junction_with_thermal_parton);
2461 
2462                 IdColInfo4.push_back(-1);
2463                 IdColInfo4.push_back(maxtag);
2464 
2465                 //TODO: give thermal partons "ANTI COLOR TAGS" to form anti junction and conserve baryon number.
2466                 JunctionInfo.push_back(IdColInfo1);
2467                 JunctionInfo.push_back(IdColInfo2);
2468                 JunctionInfo.push_back(IdColInfo3);
2469                 JunctionInfo.push_back(IdColInfo4);
2470                 Tempjunctions.push_back(JunctionInfo); // information of tempjunction is saved so et clear subordinate vector for next entry
2471                 IdColInfo1.clear();
2472                 IdColInfo2.clear();
2473                 IdColInfo3.clear();
2474                 IdColInfo4.clear();
2475                 JunctionInfo.clear();
2476               } // so far, we are finished with the list with three zeros
2477             }
2478             else if(considering[0].id() * considering[1].id() * considering[2].id() < 0){ //anti baryon would be made so temporary junction is defined
2479               //std::cout <<endl<<"Anti Baryon is made from "<<" ( "<<considering[0].acol()<<" , "<<considering[1].acol()<<" , "<<considering[2].acol()<<" ) "<<endl;
2480               //std::cout <<endl<<"Anti Baryon is made from "<<" ( "<<HH_showerptns[showerquarks[element[0]].par()].acol()<<" , "<<HH_showerptns[showerquarks[element[1]].par()].acol()<<" , "<<HH_showerptns[showerquarks[element[2]].par()].acol()<<" ) "<<endl;
2481 
2482               if(considering[0].acol() > 0 && considering[1].acol() > 0 && considering[2].acol() > 0){
2483                 IdColInfo1.push_back(1); // junction tag(1)
2484                 IdColInfo1.push_back(junction_with_thermal_parton); // zero(just room for the other usage)   : {1, 0} at 1st
2485                 IdColInfo2.push_back(1); // means color tag(positive color charge)   : { 1, color tag } at 2nd, 3rd, 4th in the vector
2486                 IdColInfo2.push_back(considering[0].acol());
2487                 IdColInfo3.push_back(1);
2488                 IdColInfo3.push_back(considering[1].acol());
2489                 IdColInfo4.push_back(1);
2490                 IdColInfo4.push_back(considering[2].acol());
2491 
2492                 JunctionInfo.push_back(IdColInfo1);
2493                 JunctionInfo.push_back(IdColInfo2);
2494                 JunctionInfo.push_back(IdColInfo3);
2495                 JunctionInfo.push_back(IdColInfo4);
2496 
2497                 Tempjunctions.push_back(JunctionInfo); // information of tempjunction is saved so et clear subordinate vector for next entry
2498 
2499                 IdColInfo1.clear();
2500                 IdColInfo2.clear();
2501                 IdColInfo3.clear();
2502                 IdColInfo4.clear();
2503                 JunctionInfo.clear();
2504 
2505                 //Since Baryon is formed, color tag for neutrality should be added, casting int into double is needed!!(ex (double) intvalue
2506                 int coltag1 = considering[0].acol();
2507                 int coltag2 = considering[1].acol();
2508                 int coltag3 = considering[2].acol();
2509                 if(coltag1 > 0 && coltag2 > 0 && coltag3 > 0 && coltag1 <= limit  && coltag2 <= limit  && coltag3 <= limit ){
2510                   double tag1 = (double)coltag1;  // they are casted to be inserted into the matrix(since it's vector of double
2511                   double tag2 = (double)coltag2;
2512                   double tag3 = (double)coltag3;
2513                   std::vector<int>::iterator I1 = std::find(IndiceForColFin.begin(), IndiceForColFin.end(), coltag1);
2514                   std::vector<int>::iterator I2 = std::find(IndiceForColFin.begin(), IndiceForColFin.end(), coltag2);
2515                   std::vector<int>::iterator I3 = std::find(IndiceForColFin.begin(), IndiceForColFin.end(), coltag3);
2516                   int loc1 = std::distance(IndiceForColFin.begin(), I1);
2517                   int loc2 = std::distance(IndiceForColFin.begin(), I2);
2518                   int loc3 = std::distance(IndiceForColFin.begin(), I3); //set up for find matrix indices corresponding to the color tags (we just found the corresponding indice in BaryonrecoMatrix1 with col tags )
2519 
2520                   BaryonrecoMatrix1.at(loc1).at(loc2).at(1) = tag3;
2521                   BaryonrecoMatrix1.at(loc2).at(loc1).at(1) = tag3;
2522                   BaryonrecoMatrix1.at(loc2).at(loc3).at(1) = tag1;
2523                   BaryonrecoMatrix1.at(loc3).at(loc2).at(1) = tag1;
2524                   BaryonrecoMatrix1.at(loc1).at(loc3).at(1) = tag2;
2525                   BaryonrecoMatrix1.at(loc3).at(loc1).at(1) = tag2; // now the color tag info for color neutrality is saved in Matrix, also we need to consider the impact from this to Meson Formation
2526 
2527                   //MesonrecoMatrix1 is modified by below
2528                   MesonrecoMatrix1.at(loc1).at(loc2) = 0;
2529                   MesonrecoMatrix1.at(loc2).at(loc1) = 0;
2530                   MesonrecoMatrix1.at(loc2).at(loc3) = 0;
2531                   MesonrecoMatrix1.at(loc3).at(loc2) = 0;
2532                   MesonrecoMatrix1.at(loc1).at(loc3) = 0;
2533                   MesonrecoMatrix1.at(loc3).at(loc1) = 0; // since three color tags of baryon are different from each other, so that these tags can't form meson with each other.
2534                 }
2535               }
2536               if(considering[0].acol() > 0 && considering[1].acol() == 0 && considering[2].acol() > 0){ // MAT + Therm/LBT + MAT case
2537                 IdColInfo1.push_back(1); // junction tag(1)
2538 
2539                 maxtag++;
2540                 int loc = findcloserepl(considering[1], perm2[q2], true, true, showerquarks, HH_thermal);
2541                 if(loc == 999999999){
2542                   //std::cout <<endl<<"Warning : extra parton used for string repair!!"<<endl;
2543                   HHparton fakep = considering[1]; fakep.id(-fakep.id());  fakep.col(maxtag);
2544                   fakep.mass(pythia.particleData.m0(std::abs(fakep.id())));
2545                   fakep.px(0.); fakep.py(0.); fakep.pz(0.);
2546                   fakep.e(fakep.mass());
2547                   fakep.is_fakeparton(true);
2548                   Extraparton.add(fakep);
2549                   junction_with_thermal_parton = 1;
2550                   //somewhere, we need to make for loop to toss all partons to remnants list.
2551                 }
2552                 else if (loc > 0){showerquarks[loc - 1].col(maxtag); }
2553                 else if(loc < 0){HH_thermal[-loc - 1].col(maxtag); junction_with_thermal_parton = 1;}
2554 
2555                 IdColInfo1.push_back(junction_with_thermal_parton);
2556 
2557                 IdColInfo2.push_back(1); // color tag
2558                 IdColInfo2.push_back(considering[0].acol());// {1, color tag} will be at 2nd, 3rd, 4th
2559                 IdColInfo3.push_back(1);
2560                 IdColInfo3.push_back(maxtag);
2561                 IdColInfo4.push_back(1);
2562                 IdColInfo4.push_back(considering[2].acol());
2563 
2564                 JunctionInfo.push_back(IdColInfo1);
2565                 JunctionInfo.push_back(IdColInfo2);
2566                 JunctionInfo.push_back(IdColInfo3);
2567                 JunctionInfo.push_back(IdColInfo4);
2568 
2569                 Tempjunctions.push_back(JunctionInfo); // information of tempjunction is saved so et clear subordinate vector for next entry
2570 
2571                 IdColInfo1.clear();
2572                 IdColInfo2.clear();
2573                 IdColInfo3.clear();
2574                 IdColInfo4.clear();
2575                 JunctionInfo.clear();
2576               }
2577               if(considering[0].acol() == 0 && considering[1].acol() > 0 && considering[2].acol() > 0){ // LBT + MAT + MAT case
2578                 IdColInfo1.push_back(1); // junction tag(1)
2579 
2580                 maxtag++;
2581                 int loc = findcloserepl(considering[0], element[0] + 1, true, true, showerquarks, HH_thermal);
2582                 if(loc == 999999999){
2583                   //std::cout <<endl<<"Warning : extra parton used for string repair!!"<<endl;
2584                   HHparton fakep = considering[0]; fakep.id(-fakep.id());  fakep.col(maxtag);
2585                   fakep.mass(pythia.particleData.m0(std::abs(fakep.id())));
2586                   fakep.px(0.); fakep.py(0.); fakep.pz(0.);
2587                   fakep.e(fakep.mass());
2588                   fakep.is_fakeparton(true);
2589                   Extraparton.add(fakep);
2590                   junction_with_thermal_parton = 1;
2591                   //somewhere, we need to make for loop to toss all partons to remnants list.
2592                 }
2593                 else if (loc > 0){showerquarks[loc - 1].col(maxtag); }
2594                 else if(loc < 0){HH_thermal[-loc - 1].col(maxtag); junction_with_thermal_parton = 1;}
2595 
2596                 IdColInfo1.push_back(junction_with_thermal_parton);
2597 
2598                 IdColInfo2.push_back(1); // means color tag
2599                 IdColInfo2.push_back(maxtag);// {1, color tag} will be at 2nd, 3rd, 4th
2600                 IdColInfo3.push_back(1);
2601                 IdColInfo3.push_back(considering[1].acol());
2602                 IdColInfo4.push_back(1);
2603                 IdColInfo4.push_back(considering[2].acol());
2604 
2605                 JunctionInfo.push_back(IdColInfo1);
2606                 JunctionInfo.push_back(IdColInfo2);
2607                 JunctionInfo.push_back(IdColInfo3);
2608                 JunctionInfo.push_back(IdColInfo4);
2609 
2610                 Tempjunctions.push_back(JunctionInfo); // information of tempjunction is saved so et clear subordinate vector for next entry
2611 
2612                 IdColInfo1.clear();
2613                 IdColInfo2.clear();
2614                 IdColInfo3.clear();
2615                 IdColInfo4.clear();
2616                 JunctionInfo.clear();
2617               }
2618               if(considering[0].acol() > 0 && considering[1].acol() > 0 && considering[2].acol() == 0){ // MAT + MAT + Therm/LBT case
2619                 IdColInfo1.push_back(1); // junction tag(1)
2620 
2621                 maxtag++;
2622                 int loc = findcloserepl(considering[2], perm2[q3], true, true, showerquarks, HH_thermal);
2623                 if(loc == 999999999){
2624                   //std::cout <<endl<<"Warning : extra parton used for string repair!!"<<endl;
2625                   HHparton fakep = considering[2]; fakep.id(-fakep.id());  fakep.col(maxtag);
2626                   fakep.mass(pythia.particleData.m0(std::abs(fakep.id())));
2627                   fakep.px(0.); fakep.py(0.); fakep.pz(0.);
2628                   fakep.e(fakep.mass());
2629                   fakep.is_fakeparton(true);
2630                   Extraparton.add(fakep);
2631                   junction_with_thermal_parton = 1;
2632                   //somewhere, we need to make for loop to toss all partons to remnants list.
2633                 }
2634                 else if (loc > 0){showerquarks[loc - 1].col(maxtag); }
2635                 else if(loc < 0){HH_thermal[-loc - 1].col(maxtag); junction_with_thermal_parton = 1;}
2636 
2637                 IdColInfo1.push_back(junction_with_thermal_parton);
2638 
2639                 IdColInfo2.push_back(1); // means color tag
2640                 IdColInfo2.push_back(considering[0].acol());// {1, color tag} will be at 2nd, 3rd, 4th
2641                 IdColInfo3.push_back(1);
2642                 IdColInfo3.push_back(considering[1].acol());
2643                 IdColInfo4.push_back(1);
2644                 IdColInfo4.push_back(maxtag);
2645 
2646                 JunctionInfo.push_back(IdColInfo1);
2647                 JunctionInfo.push_back(IdColInfo2);
2648                 JunctionInfo.push_back(IdColInfo3);
2649                 JunctionInfo.push_back(IdColInfo4);
2650 
2651                 Tempjunctions.push_back(JunctionInfo); // information of tempjunction is saved so et clear subordinate vector for next entry
2652 
2653                 IdColInfo1.clear();
2654                 IdColInfo2.clear();
2655                 IdColInfo3.clear();
2656                 IdColInfo4.clear();
2657                 JunctionInfo.clear();
2658               } // so far, we are finished with the list with one zero component.
2659               if(considering[0].acol() > 0 && considering[1].acol() == 0 && considering[2].acol() == 0){ // MAT + Therm/LBT + Therm/LBT case
2660                 IdColInfo1.push_back(1); // junction tag(1)
2661                 IdColInfo2.push_back(1); // means color tag
2662                 IdColInfo2.push_back(considering[0].acol());// {1, color tag} will be at 2nd, 3rd, 4th
2663 
2664                 maxtag++;
2665                 int loc1 = findcloserepl(considering[1], perm2[q2], true, true, showerquarks, HH_thermal);
2666                 if(loc1 == 999999999){
2667                   //std::cout <<endl<<"Warning : extra parton used for string repair!!"<<endl;
2668                   HHparton fakep = considering[1]; fakep.id(-fakep.id());  fakep.col(maxtag);
2669                   fakep.mass(pythia.particleData.m0(std::abs(fakep.id())));
2670                   fakep.px(0.); fakep.py(0.); fakep.pz(0.);
2671                   fakep.e(fakep.mass());
2672                   fakep.is_fakeparton(true);
2673                   Extraparton.add(fakep);
2674                   junction_with_thermal_parton = 1;
2675                   //somewhere, we need to make for loop to toss all partons to remnants list.
2676                 }
2677                 else if (loc1 > 0){showerquarks[loc1 - 1].col(maxtag); }
2678                 else if(loc1 < 0){HH_thermal[-loc1 - 1].col(maxtag); junction_with_thermal_parton = 1;}
2679                 IdColInfo3.push_back(1);
2680                 IdColInfo3.push_back(maxtag);
2681 
2682                 maxtag++;
2683                 int loc2 = findcloserepl(considering[2], perm2[q3], true, true, showerquarks, HH_thermal);
2684                 if(loc2 == 999999999){
2685                   //std::cout <<endl<<"Warning : extra parton used for string repair!!"<<endl;
2686                   HHparton fakep = considering[2]; fakep.id(-fakep.id());  fakep.col(maxtag);
2687                   fakep.mass(pythia.particleData.m0(std::abs(fakep.id())));
2688                   fakep.px(0.); fakep.py(0.); fakep.pz(0.);
2689                   fakep.e(fakep.mass());
2690                   fakep.is_fakeparton(true);
2691                   Extraparton.add(fakep);
2692                   junction_with_thermal_parton = 1;
2693                   //somewhere, we need to make for loop to toss all partons to remnants list.
2694                 }
2695                 else if (loc2 > 0){showerquarks[loc2 - 1].col(maxtag); }
2696                 else if(loc2 < 0){HH_thermal[-loc2 - 1].col(maxtag); junction_with_thermal_parton = 1;}
2697 
2698                 IdColInfo1.push_back(junction_with_thermal_parton);
2699 
2700                 IdColInfo4.push_back(1);
2701                 IdColInfo4.push_back(maxtag);
2702                 //TODO: give thermal partons "ANTI COLOR TAGS" to form anti junction and conserve baryon number.
2703 
2704                 JunctionInfo.push_back(IdColInfo1);
2705                 JunctionInfo.push_back(IdColInfo2);
2706                 JunctionInfo.push_back(IdColInfo3);
2707                 JunctionInfo.push_back(IdColInfo4);
2708 
2709                 Tempjunctions.push_back(JunctionInfo); // information of tempjunction is saved so et clear subordinate vector for next entry
2710 
2711                 IdColInfo1.clear();
2712                 IdColInfo2.clear();
2713                 IdColInfo3.clear();
2714                 IdColInfo4.clear();
2715                 JunctionInfo.clear();
2716               }
2717               if(considering[0].acol() == 0 && considering[1].acol() == 0 && considering[2].acol() > 0){ // Therm/LBT + Therm/LBT + MAT case
2718                 IdColInfo1.push_back(1); // junction tag(1)
2719 
2720                 maxtag++;
2721                 int loc1 = findcloserepl(considering[0], element[0] + 1, true, true, showerquarks, HH_thermal);
2722                 if(loc1 == 999999999){
2723                   //std::cout <<endl<<"Warning : extra parton used for string repair!!"<<endl;
2724                   HHparton fakep = considering[0]; fakep.id(-fakep.id());  fakep.col(maxtag);
2725                   fakep.mass(pythia.particleData.m0(std::abs(fakep.id())));
2726                   fakep.px(0.); fakep.py(0.); fakep.pz(0.);
2727                   fakep.e(fakep.mass());
2728                   fakep.is_fakeparton(true);
2729                   Extraparton.add(fakep);
2730                   junction_with_thermal_parton = 1;
2731                   //somewhere, we need to make for loop to toss all partons to remnants list.
2732                 }
2733                 else if (loc1 > 0){showerquarks[loc1 - 1].col(maxtag); }
2734                 else if(loc1 < 0){HH_thermal[-loc1 - 1].col(maxtag); junction_with_thermal_parton = 1;}
2735                 IdColInfo2.push_back(1);
2736                 IdColInfo2.push_back(maxtag);
2737 
2738                 maxtag++;
2739                 int loc2 = findcloserepl(considering[1], perm2[q2], true, true, showerquarks, HH_thermal);
2740                 if(loc2 == 999999999){
2741                   //std::cout <<endl<<"Warning : extra parton used for string repair!!"<<endl;
2742                   HHparton fakep = considering[1]; fakep.id(-fakep.id());  fakep.col(maxtag);
2743                   fakep.mass(pythia.particleData.m0(std::abs(fakep.id())));
2744                   fakep.px(0.); fakep.py(0.); fakep.pz(0.);
2745                   fakep.e(fakep.mass());
2746                   fakep.is_fakeparton(true);
2747                   Extraparton.add(fakep);
2748                   junction_with_thermal_parton = 1;
2749                   //somewhere, we need to make for loop to toss all partons to remnants list.
2750                 }
2751                 else if (loc2 > 0){showerquarks[loc2 - 1].col(maxtag); }
2752                 else if(loc2 < 0){HH_thermal[-loc2 - 1].col(maxtag); junction_with_thermal_parton = 1;}
2753 
2754                 IdColInfo1.push_back(junction_with_thermal_parton);
2755 
2756                 IdColInfo3.push_back(1);
2757                 IdColInfo3.push_back(maxtag);
2758 
2759                 IdColInfo4.push_back(1); // means color tag
2760                 IdColInfo4.push_back(considering[2].acol());// {1, color tag} will be at 2nd, 3rd, 4th
2761 
2762                 JunctionInfo.push_back(IdColInfo1);
2763                 JunctionInfo.push_back(IdColInfo2);
2764                 JunctionInfo.push_back(IdColInfo3);
2765                 JunctionInfo.push_back(IdColInfo4);
2766 
2767                 Tempjunctions.push_back(JunctionInfo); // information of tempjunction is saved so et clear subordinate vector for next entry
2768 
2769                 IdColInfo1.clear();
2770                 IdColInfo2.clear();
2771                 IdColInfo3.clear();
2772                 IdColInfo4.clear();
2773                 JunctionInfo.clear();
2774               }
2775               if(considering[0].acol() == 0 && considering[1].acol() > 0 && considering[2].acol() == 0){ // Therm/LBT + Therm/LBT + MAT case
2776                 IdColInfo1.push_back(1); // junction tag(1)
2777 
2778                 maxtag++;
2779                 int loc1 = findcloserepl(considering[0], element[0] + 1, true, true, showerquarks, HH_thermal);
2780                 if(loc1 == 999999999){
2781                   //std::cout <<endl<<"Warning : extra parton used for string repair!!"<<endl;
2782                   HHparton fakep = considering[0]; fakep.id(-fakep.id());  fakep.col(maxtag);
2783                   fakep.mass(pythia.particleData.m0(std::abs(fakep.id())));
2784                   fakep.px(0.); fakep.py(0.); fakep.pz(0.);
2785                   fakep.e(fakep.mass());
2786                   fakep.is_fakeparton(true);
2787                   Extraparton.add(fakep);
2788                   junction_with_thermal_parton = 1;
2789                   //somewhere, we need to make for loop to toss all partons to remnants list.
2790                 }
2791                 else if (loc1 > 0){showerquarks[loc1 - 1].col(maxtag); }
2792                 else if(loc1 < 0){HH_thermal[-loc1 - 1].col(maxtag); junction_with_thermal_parton = 1;}
2793                 IdColInfo2.push_back(1);
2794                 IdColInfo2.push_back(maxtag);
2795 
2796                 IdColInfo3.push_back(1); // means color tag
2797                 IdColInfo3.push_back(considering[1].acol());// {1, color tag} will be at 2nd, 3rd, 4th
2798 
2799                 maxtag++;
2800                 int loc2 = findcloserepl(considering[2], perm2[q3], true, true, showerquarks, HH_thermal);
2801                 if(loc2 == 999999999){
2802                   //std::cout <<endl<<"Warning : extra parton used for string repair!!"<<endl;
2803                   HHparton fakep = considering[2]; fakep.id(-fakep.id());  fakep.col(maxtag);
2804                   fakep.mass(pythia.particleData.m0(std::abs(fakep.id())));
2805                   fakep.px(0.); fakep.py(0.); fakep.pz(0.);
2806                   fakep.e(fakep.mass());
2807                   fakep.is_fakeparton(true);
2808                   Extraparton.add(fakep);
2809                   junction_with_thermal_parton = 1;
2810                   //somewhere, we need to make for loop to toss all partons to remnants list.
2811                 }
2812                 else if (loc2 > 0){showerquarks[loc2 - 1].col(maxtag); }
2813                 else if(loc2 < 0){HH_thermal[-loc2 - 1].col(maxtag); junction_with_thermal_parton = 1;}
2814 
2815                 IdColInfo1.push_back(junction_with_thermal_parton);
2816 
2817                 IdColInfo4.push_back(1);
2818                 IdColInfo4.push_back(maxtag);
2819 
2820                 JunctionInfo.push_back(IdColInfo1);
2821                 JunctionInfo.push_back(IdColInfo2);
2822                 JunctionInfo.push_back(IdColInfo3);
2823                 JunctionInfo.push_back(IdColInfo4);
2824 
2825                 Tempjunctions.push_back(JunctionInfo); // information of tempjunction is saved so et clear subordinate vector for next entry
2826 
2827                 IdColInfo1.clear();
2828                 IdColInfo2.clear();
2829                 IdColInfo3.clear();
2830                 IdColInfo4.clear();
2831                 JunctionInfo.clear();
2832               } // so far, we are finished with the list with two zeros
2833               if(considering[0].acol() == 0 && considering[1].acol() == 0 && considering[2].acol() == 0){ // Therm/LBT + Therm/LBT + Therm/LBT
2834                 IdColInfo1.push_back(1); // junction tag(1)
2835 
2836                 maxtag++;
2837                 int loc1 = findcloserepl(considering[0], element[0] + 1, true, true, showerquarks, HH_thermal);
2838                 if(loc1 == 999999999){
2839                   //std::cout <<endl<<"Warning : extra parton used for string repair!!"<<endl;
2840                   HHparton fakep = considering[0]; fakep.id(-fakep.id());  fakep.col(maxtag);
2841                   fakep.mass(pythia.particleData.m0(std::abs(fakep.id())));
2842                   fakep.px(0.); fakep.py(0.); fakep.pz(0.);
2843                   fakep.e(fakep.mass());
2844                   fakep.is_fakeparton(true);
2845                   Extraparton.add(fakep);
2846                   junction_with_thermal_parton = 1;
2847                   //somewhere, we need to make for loop to toss all partons to remnants list.
2848                 }
2849                 else if (loc1 > 0){showerquarks[loc1 - 1].col(maxtag); }
2850                 else if(loc1 < 0){HH_thermal[-loc1 - 1].col(maxtag); junction_with_thermal_parton = 1;}
2851                 IdColInfo2.push_back(1);
2852                 IdColInfo2.push_back(maxtag);
2853 
2854                 maxtag++;
2855                 int loc2 = findcloserepl(considering[1], perm2[q2], true, true, showerquarks, HH_thermal);
2856                 if(loc2 == 999999999){
2857                   //std::cout <<endl<<"Warning : extra parton used for string repair!!"<<endl;
2858                   HHparton fakep = considering[1]; fakep.id(-fakep.id());  fakep.col(maxtag);
2859                   fakep.mass(pythia.particleData.m0(std::abs(fakep.id())));
2860                   fakep.px(0.); fakep.py(0.); fakep.pz(0.);
2861                   fakep.e(fakep.mass());
2862                   fakep.is_fakeparton(true);
2863                   Extraparton.add(fakep);
2864                   junction_with_thermal_parton = 1;
2865                   //somewhere, we need to make for loop to toss all partons to remnants list.
2866                 }
2867                 else if (loc2 > 0){showerquarks[loc2 - 1].col(maxtag); }
2868                 else if(loc2 < 0){HH_thermal[-loc2 - 1].col(maxtag); junction_with_thermal_parton = 1;}
2869                 IdColInfo3.push_back(1);
2870                 IdColInfo3.push_back(maxtag);
2871 
2872                 maxtag++;
2873                 int loc3 = findcloserepl(considering[2], perm2[q3], true, true, showerquarks, HH_thermal);
2874                 if(loc3 == 999999999){
2875                   //std::cout <<endl<<"Warning : extra parton used for string repair!!"<<endl;
2876                   HHparton fakep = considering[2]; fakep.id(-fakep.id());  fakep.col(maxtag);
2877                   fakep.mass(pythia.particleData.m0(std::abs(fakep.id())));
2878                   fakep.px(0.); fakep.py(0.); fakep.pz(0.);
2879                   fakep.e(fakep.mass());
2880                   fakep.is_fakeparton(true);
2881                   Extraparton.add(fakep);
2882                   junction_with_thermal_parton = 1;
2883                   //somewhere, we need to make for loop to toss all partons to remnants list.
2884                 }
2885                 else if (loc3 > 0){showerquarks[loc3 - 1].col(maxtag); }
2886                 else if(loc3 < 0){HH_thermal[-loc3 - 1].col(maxtag); junction_with_thermal_parton = 1;}
2887 
2888                 IdColInfo1.push_back(junction_with_thermal_parton);
2889 
2890                 IdColInfo4.push_back(1);
2891                 IdColInfo4.push_back(maxtag);
2892 
2893                 JunctionInfo.push_back(IdColInfo1);
2894                 JunctionInfo.push_back(IdColInfo2);
2895                 JunctionInfo.push_back(IdColInfo3);
2896                 JunctionInfo.push_back(IdColInfo4);
2897                 Tempjunctions.push_back(JunctionInfo); // information of tempjunction is saved so et clear subordinate vector for next entry
2898                 IdColInfo1.clear();
2899                 IdColInfo2.clear();
2900                 IdColInfo3.clear();
2901                 IdColInfo4.clear();
2902                 JunctionInfo.clear();
2903               } // so far, we are finished with the list with three zeros
2904                //dignostic measure
2905                /*
2906                std::cout <<endl<<"Meson reco Matrix revised by Baryon formation is same as below"<<endl;
2907                for(int irow=0; irow < IndiceForColFin.size(); irow++){
2908                    for(int icol=0; icol < IndiceForColFin.size(); icol++){
2909                    std::cout <<"  "<<MesonrecoMatrix1.at(irow).at(icol)<<"  ";
2910                    }
2911                std::cout <<endl<<endl;
2912                }
2913                */
2914             }
2915 
2916                     //now we're forming the hadron
2917                     HHhadron formedhadron;
2918                     //setting the hadron values: is a recombined hadron, mass, and parents
2919                     formedhadron.is_recohad(true); formedhadron.mass( p_BCM[0].t() + p_BCM[1].t() + p_BCM[2].t() );
2920                     formedhadron.add_par(showerquarks[element[0]].par());
2921                     if(perm2[q2]>0){formedhadron.add_par(showerquarks[element[1]].par());}else{formedhadron.add_par(element[1]);}
2922                     if(perm2[q3]>0){formedhadron.add_par(showerquarks[element[2]].par());}else{formedhadron.add_par(element[2]);}
2923 
2924                     //now setting if baryon is in excited state
2925                     if(WigB[0]*recofactor3*mult < rndbaryon){formedhadron.is_excited(true);}
2926 
2927                     //setting if there are any thermal partons used to make the hadron (with the '0' thermal parent as -99999 so that it doesn't conflict with '0' shower parton)
2928                     if(     perm2[q2]>0 && perm2[q3]>0){/*is sh-sh-sh*/ formedhadron.is_shsh(true);}
2929                     else if(perm2[q2]>0 && perm2[q3]<0){/*is sh-sh-th*/ formedhadron.is_shth(true); if(element[2] == 0){formedhadron.parents[2] = -99999;}}
2930                     else if(perm2[q2]<0 && perm2[q3]>0){/*is sh-th-sh*/ formedhadron.is_shth(true); if(element[1] == 0){formedhadron.parents[1] = -99999;}}
2931                     else if(perm2[q2]<0 && perm2[q3]<0){/*is sh-th-th*/ formedhadron.is_shth(true); if(element[1] == 0){formedhadron.parents[1] = -99999;}
2932                                                                                                       if(element[2] == 0){formedhadron.parents[2] = -99999;}
2933                     }
2934 
2935                     //setting hadron position and momentum vectors
2936                     Pbaryon.Set(Pbaryon.x(),Pbaryon.y(),Pbaryon.z(),sqrt(Pbaryon.x()*Pbaryon.x() + Pbaryon.y()*Pbaryon.y() + Pbaryon.z()*Pbaryon.z() + formedhadron.mass()*formedhadron.mass()));
2937                     formedhadron.pos(pos_lab); formedhadron.P(Pbaryon);
2938 
2939                     //setting hadron color tags (for tracing colors of the constituent partons) [**]
2940                     //will need to update to reflect color tags given to random (thermal/lbt) partons
2941                     formedhadron.add_col((considering[0].col()>0)?considering[0].col():considering[0].acol());
2942                     formedhadron.add_col((considering[1].col()>0)?considering[1].col():considering[1].acol());
2943                     formedhadron.add_col((considering[2].col()>0)?considering[2].col():considering[2].acol());
2944 
2945                     //need to choose *what* hadron we've formed... base this on the parton id's, mass, & if excited
2946                     //might want to do this differently? void f'n(partoncollection, formedhadron)?
2947                     set_baryon_id(considering, formedhadron);
2948 
2949                     //need to add the hadron to the collection
2950                     HH_hadrons.add(formedhadron);
2951 
2952                     //now that we've formed the hadron, need to set ALL (3) the 'considering' flags to used
2953                                     showerquarks[element[0]].status(1); showerquarks[element[0]].is_used(true);
2954                     if(perm2[q2]>0){showerquarks[element[1]].status(1); showerquarks[element[1]].is_used(true);}
2955                     else{            HH_thermal[-element[1]].status(1);  HH_thermal[-element[1]].is_used(true);}
2956                     if(perm2[q3]>0){showerquarks[element[2]].status(1); showerquarks[element[2]].is_used(true);}
2957                     else{            HH_thermal[-element[2]].status(1);  HH_thermal[-element[2]].is_used(true);}
2958 
2959                     madehadron = true; considering.clear();
2960                     break;
2961                   }
2962                   else{
2963                     //since we've not formed a baryon on this try, need to revert the third quark 'considering' used flag
2964                     if(perm2[q3]>0){showerquarks[element[2]].status(0);}
2965                     else{            HH_thermal[-element[2]].status(0);}
2966 
2967                     //and remove the third entry in considering
2968                     considering.partons.pop_back();
2969                   }
2970               }
2971       }else if(considering[0].id()*considering[1].id() < 0){
2972         //Key point is determing recofactor2
2973         if(considering[0].id() > 0 && considering[1].id() < 0){
2974           int tag0 = considering[0].col();
2975           int tag1 = considering[1].acol();
2976           if(tag0 > 0 && tag1 > 0 && tag0 <= limit  && tag1 <= limit ){
2977             std::vector<int>::iterator L1 = std::find(IndiceForColFin.begin(), IndiceForColFin.end(), tag0);
2978             std::vector<int>::iterator L2 = std::find(IndiceForColFin.begin(), IndiceForColFin.end(), tag1);
2979             int indexMatrix1 = std::distance(IndiceForColFin.begin(), L1);
2980             int indexMatrix2 = std::distance(IndiceForColFin.begin(), L2);
2981 
2982             recofactor2 = (MesonrecoMatrix1.at(indexMatrix1).at(indexMatrix2));
2983             //std::cout <<endl<<" the recofactor for meson is "<<(MesonrecoMatrix1.at(indexMatrix1).at(indexMatrix2))<<endl;
2984           }
2985           else{recofactor2 = 1./9.;}
2986         }
2987         else if(considering[1].id() > 0 && considering[0].id() < 0){
2988           int tag0 = considering[1].col();
2989           int tag1 = considering[0].acol();
2990           if(tag0 > 0 && tag1 > 0 && tag0 <= limit && tag1 <= limit){
2991             std::vector<int>::iterator L1 = std::find(IndiceForColFin.begin(), IndiceForColFin.end(), tag0);
2992             std::vector<int>::iterator L2 = std::find(IndiceForColFin.begin(), IndiceForColFin.end(), tag1);
2993             int indexMatrix1 = std::distance(IndiceForColFin.begin(), L1);
2994             int indexMatrix2 = std::distance(IndiceForColFin.begin(), L2);
2995 
2996             recofactor2 = (MesonrecoMatrix1.at(indexMatrix1).at(indexMatrix2));
2997           }
2998           else{recofactor2 = 1./9.;}
2999           //std::cout <<endl<<" the recofactor for meson is "<<(MesonrecoMatrix1.at(indexMatrix1).at(indexMatrix2))<<endl;
3000         }
3001                 //now that we *could* form a meson, now we check if we actually do form one
3002                 //meson momentum
3003                 FourVector Pmeson;
3004                 Pmeson.Set(considering[0].px()+considering[1].px(),considering[0].py()+considering[1].py(),considering[0].pz()+considering[1].pz(),0.);
3005 
3006                 //meson(CM) velocity
3007                 FourVector betaM;
3008                 betaM.Set(Pmeson.x()/(considering[0].e()+considering[1].e()),Pmeson.y()/(considering[0].e()+considering[1].e()),Pmeson.z()/(considering[0].e()+considering[1].e()),0.);
3009                 betaM.Set(betaM.x(),betaM.y(),betaM.z(),1./(sqrt(1.-(betaM.x()*betaM.x() + betaM.y()*betaM.y() + betaM.z()*betaM.z()))));
3010 
3011                 //boosting into CM frame
3012                 FourVector pos_MCM[2], p_MCM[2];
3013                 pos_MCM[0] = considering[0].boost_pos(betaM); pos_MCM[1] = considering[1].boost_pos(betaM);
3014                   p_MCM[0] = considering[0].boost_P(betaM);     p_MCM[1] = considering[1].boost_P(betaM);
3015 
3016                 //velocities in CM frame
3017                 FourVector v_MCM[2];
3018                 v_MCM[0].Set(p_MCM[0].x()/p_MCM[0].t(),p_MCM[0].y()/p_MCM[0].t(),p_MCM[0].z()/p_MCM[0].t(),0.);
3019                 v_MCM[1].Set(p_MCM[1].x()/p_MCM[1].t(),p_MCM[1].y()/p_MCM[1].t(),p_MCM[1].z()/p_MCM[1].t(),0.);
3020 
3021                 //propagating quarks until time of youngest quark
3022                 //is just max(pos_MCM[0].t(), pos_MCM[1].t());
3023                 double curtime = (pos_MCM[0].t() > pos_MCM[1].t()) ? pos_MCM[0].t() : pos_MCM[1].t();
3024                 FourVector cur_pos[2];
3025                 cur_pos[0].Set(pos_MCM[0].x()+v_MCM[0].x()*(curtime-pos_MCM[0].t()),pos_MCM[0].y()+v_MCM[0].y()*(curtime-pos_MCM[0].t()),pos_MCM[0].z()+v_MCM[0].z()*(curtime-pos_MCM[0].t()),curtime);
3026                 cur_pos[1].Set(pos_MCM[1].x()+v_MCM[1].x()*(curtime-pos_MCM[1].t()),pos_MCM[1].y()+v_MCM[1].y()*(curtime-pos_MCM[1].t()),pos_MCM[1].z()+v_MCM[1].z()*(curtime-pos_MCM[1].t()),curtime);
3027 
3028                 //finding position of CM at curtime
3029                 FourVector pos_CM;
3030                 pos_CM.Set(
3031                 (cur_pos[0].x()*considering[0].mass()+cur_pos[1].x()*considering[1].mass())/(considering[0].mass()+considering[1].mass()),
3032                 (cur_pos[0].y()*considering[0].mass()+cur_pos[1].y()*considering[1].mass())/(considering[0].mass()+considering[1].mass()),
3033                 (cur_pos[0].z()*considering[0].mass()+cur_pos[1].z()*considering[1].mass())/(considering[0].mass()+considering[1].mass()),
3034                 curtime);
3035 
3036                 //finding position of meson in lab frame
3037                 betaM.Set(-betaM.x(),-betaM.y(),-betaM.z(),betaM.t());
3038                 FourVector pos_lab = HHboost(betaM, pos_CM);
3039 
3040                 //finding the squares of the relative momenta of partons in CM frame
3041                 FourVector k_rel_square;
3042         double sum_mass_square = (considering[0].mass()+considering[1].mass())*(considering[0].mass()+considering[1].mass());
3043                 k_rel_square.Set(std::pow(considering[1].mass()*p_MCM[0].x()-considering[0].mass()*p_MCM[1].x(),2.)/sum_mass_square,std::pow(considering[1].mass()*p_MCM[0].y()-considering[0].mass()*p_MCM[1].y(),2.)/sum_mass_square,std::pow(considering[1].mass()*p_MCM[0].z()-considering[0].mass()*p_MCM[1].z(),2.)/sum_mass_square,0.);
3044                 k_rel_square.Set(k_rel_square.x(),k_rel_square.y(),k_rel_square.z(),k_rel_square.x()+k_rel_square.y()+k_rel_square.z());
3045 
3046                 //finding the squares of relative positions of partons in CM frame
3047                 FourVector pos_rel_square;
3048                 pos_rel_square.Set((cur_pos[0].x()-cur_pos[1].x())*(cur_pos[0].x()-cur_pos[1].x()),(cur_pos[0].y()-cur_pos[1].y())*(cur_pos[0].y()-cur_pos[1].y()),(cur_pos[0].z()-cur_pos[1].z())*(cur_pos[0].z()-cur_pos[1].z()),0.);
3049                 pos_rel_square.Set(pos_rel_square.x(),pos_rel_square.y(),pos_rel_square.z(),pos_rel_square.x()+pos_rel_square.y()+pos_rel_square.z());
3050 
3051                 //setting appropriate sigma...
3052                 double SigM2 = SigPi2;
3053                 int sortid[2] = {0,0};
3054                 if(std::abs(considering[0].id()) >= std::abs(considering[1].id())){sortid[0] = std::abs(considering[0].id()); sortid[1] = std::abs(considering[1].id());}
3055                 else{sortid[0] = std::abs(considering[1].id()); sortid[1] = std::abs(considering[0].id());}
3056 
3057                 if(     sortid[0] == 3){
3058                     if(     sortid[1] == 3){SigM2 = SigPhi2;}
3059                     else{                   SigM2 = SigK2;}
3060                 }
3061                 else if(sortid[0] == 4){
3062                     if(     sortid[1] == 4){SigM2 = SigJpi2;}
3063                     else if(sortid[1] == 3){SigM2 = SigDs2;}
3064                     else{                   SigM2 = SigD2;}
3065                 }
3066                 else if(sortid[0] == 5){
3067                     if(     sortid[1] == 5){SigM2 = SigUps2;}
3068                     else if(sortid[1] == 4){SigM2 = SigBc2;}
3069                     else if(sortid[1] == 3){SigM2 = SigB2;}
3070                     else{                   SigM2 = SigB2;}
3071                 }
3072 
3073                 double u[4];
3074         // This is the squared distance in phase space weighted with the widths
3075                 u[1] = 0.5*(pos_rel_square.x()/SigM2 + k_rel_square.x()*SigM2/hbarc2);
3076                 u[2] = 0.5*(pos_rel_square.y()/SigM2 + k_rel_square.y()*SigM2/hbarc2);
3077                 u[3] = 0.5*(pos_rel_square.z()/SigM2 + k_rel_square.z()*SigM2/hbarc2);
3078                 u[0] = u[1] + u[2] + u[3];
3079 
3080         // Ground state wave function
3081         double WigM = std::exp(-u[0]);
3082 
3083         // Computing s ~ L^2 for the system
3084         double rdotr = pos_rel_square.t();
3085                 double pdotp = k_rel_square.t();
3086                 double pdotr = std::sqrt(pos_rel_square.x())*std::sqrt(k_rel_square.x()) + std::sqrt(pos_rel_square.y())*std::sqrt(k_rel_square.y()) + std::sqrt(pos_rel_square.z())*std::sqrt(k_rel_square.z());
3087 
3088                 double s = 1/hbarc2*(pdotp*rdotr - pdotr*pdotr);
3089 
3090                 // Random number for recombination dice roll
3091                 double rndmeson = ran();
3092 
3093         // Initialize quantum numbers and recombination probability
3094         int angular_qnum = -1; // l
3095                 int radial_qnum = -1; // k
3096         double mult1 = considering[1].is_thermal() ? th_recofactor : sh_recofactor;
3097         double total_prob =  WigM*recofactor2*mult1;
3098 
3099         if(total_prob >= rndmeson)
3100         {
3101                     angular_qnum = 0;
3102                     radial_qnum = 0;
3103                 }
3104                 else
3105         {
3106           total_prob += WigM*u[0];
3107           if(total_prob >= rndmeson && maxM_level>0)
3108           {
3109                       angular_qnum = 1;
3110                       radial_qnum = 0;
3111                   }
3112                   else
3113           {
3114             total_prob += (1./2.)*WigM*((2./3.)*std::pow(u[0],2) + (1./3.)*s);
3115             if(total_prob >= rndmeson && maxM_level>1)
3116             {
3117                         angular_qnum = 2;
3118                         radial_qnum = 0;
3119                     }
3120                     else
3121             {
3122               total_prob += (1./2.)*WigM*((1./3.)*std::pow(u[0],2) - (1./3.)*s);
3123               if(total_prob >= rndmeson && maxM_level>1 )
3124               {
3125                         angular_qnum = 0;
3126                         radial_qnum = 1;
3127                       }
3128                       else
3129               {
3130                 total_prob += (1./6.)*WigM*((2./5.)*std::pow(u[0],3) + (3./5.)*u[0]*s);
3131                 if(total_prob >= rndmeson && maxM_level>2)
3132                 {
3133                             angular_qnum = 1;
3134                             radial_qnum = 1;
3135                         }
3136                         else
3137                 {
3138                   total_prob += (1./6.)*WigM*((3./5.)*std::pow(u[0],3) - (3./5.)*u[0]*s);
3139                   if(total_prob >= rndmeson && maxM_level>2)
3140                   {
3141                             angular_qnum = 3;
3142                               radial_qnum = 0;
3143                           }
3144                   else
3145                   {
3146                     total_prob += (1./120.)*WigM*std::pow((std::pow(u[0],2)-s),2);
3147                     if(total_prob >= rndmeson && maxM_level>3)
3148                     {
3149                                 angular_qnum = 0;
3150                                 radial_qnum = 2;
3151                             }
3152                     else
3153                     {
3154                       total_prob += (1./24.)*WigM*((4./7.)*std::pow(u[0],4)-(2./7.)*std::pow(u[0],2)*s-(2./7.)*std::pow(s,2));
3155                       if(total_prob >= rndmeson && maxM_level>3)
3156                       {
3157                               angular_qnum = 2;
3158                                 radial_qnum = 1;
3159                               }
3160                       else
3161                       {
3162                         total_prob += (1./24.)*WigM*((8./35.)*std::pow(u[0],4)+(24./35.)*std::pow(u[0],2)*s+(3./35.)*std::pow(s,2));
3163                         if(total_prob >= rndmeson && maxM_level>3)
3164                         {
3165                                     angular_qnum = 4;
3166                                     radial_qnum = 0;
3167                                 }
3168                       }
3169                     }
3170                   }
3171                 }
3172               }
3173             }
3174           }
3175         }
3176 
3177         //Habemus Recombinationem!
3178         if(angular_qnum >= 0) {
3179           /*std::cout << "Mesons" << std::endl;
3180           std::cout << considering[0].id() << "," << considering[0].col() << "," << considering[0].acol() << std::endl;
3181           std::cout << considering[1].id() << "," << considering[1].col() << "," << considering[1].acol() << std::endl;*/
3182           if(considering[0].id() > 0 && considering[1].id() < 0){//case of first parton is q and second is q-bar
3183             //std::cout <<endl<<"chosen partons are "<< int(considering[0].id()) << " and " << int(considering[1].id()) << endl <<endl;
3184             //std::cout <<endl<<"and their color tag is "<< int(considering[0].col()) << " and " << int(considering[1].acol()) << endl <<endl;
3185             //std::cout <<"color correction implemented as Follows: "<< considering[0].col() <<" = " << considering[1].acol()<<endl;
3186 
3187             // Overwrite non-dominant colortags in tempjunctions with dominant ones
3188             // q-qbar case
3189             if(considering[0].col() != 0 && considering[1].acol() != 0){
3190               for(int ijunc=0; ijunc<Tempjunctions.size(); ijunc++){
3191                 if(Tempjunctions.at(ijunc).at(1).at(1) == considering[1].acol()){
3192                   Tempjunctions.at(ijunc).at(1).pop_back();
3193                   Tempjunctions.at(ijunc).at(1).push_back(considering[0].col());
3194                 }
3195                     if(Tempjunctions.at(ijunc).at(2).at(1) == considering[1].acol()){
3196                   Tempjunctions.at(ijunc).at(2).pop_back();
3197                   Tempjunctions.at(ijunc).at(2).push_back(considering[0].col());
3198                 }
3199                     if(Tempjunctions.at(ijunc).at(3).at(1) == considering[1].acol()){
3200                   Tempjunctions.at(ijunc).at(3).pop_back();
3201                   Tempjunctions.at(ijunc).at(3).push_back(considering[0].col());
3202                 }
3203               }
3204             }
3205 
3206             //before changing the tags, revise the MesonrecoMatrix elements!
3207             int coltag1 = considering[0].col();
3208             int coltag2 = considering[1].acol();
3209             if(coltag1 > 0 && coltag2 > 0 && coltag1 <= limit && coltag2 <= limit){
3210               std::vector<int>::iterator I1 = std::find(IndiceForColFin.begin(), IndiceForColFin.end(), coltag1);
3211               std::vector<int>::iterator I2 = std::find(IndiceForColFin.begin(), IndiceForColFin.end(), coltag2);
3212               int loc1 = std::distance(IndiceForColFin.begin(), I1);
3213               int loc2 = std::distance(IndiceForColFin.begin(), I2); //set up for find matrix indices corresponding to the color tags
3214 
3215 
3216                         MesonrecoMatrix1.at(loc1).at(loc2) = 1;
3217               MesonrecoMatrix1.at(loc2).at(loc1) = 1; //Matrix revised
3218 
3219                         for(int iM=0;iM<MesonrecoMatrix1[0].size();++iM){
3220                 if(MesonrecoMatrix1[loc1][iM]==1){MesonrecoMatrix1[loc2][iM]=1;}
3221                             if(MesonrecoMatrix1[loc2][iM]==1){MesonrecoMatrix1[loc1][iM]=1;}
3222                             if(MesonrecoMatrix1[iM][loc1]==1){MesonrecoMatrix1[iM][loc2]=1;}
3223                             if(MesonrecoMatrix1[iM][loc2]==1){MesonrecoMatrix1[iM][loc1]=1;}
3224                             if(MesonrecoMatrix1[loc1][iM]==0){MesonrecoMatrix1[loc2][iM]=0;}
3225                             if(MesonrecoMatrix1[loc2][iM]==0){MesonrecoMatrix1[loc1][iM]=0;}
3226                             if(MesonrecoMatrix1[iM][loc1]==0){MesonrecoMatrix1[iM][loc2]=0;}
3227                             if(MesonrecoMatrix1[iM][loc2]==0){MesonrecoMatrix1[iM][loc1]=0;}
3228                         }
3229               /*
3230               std::cout <<endl<<"Revised Matrix is same as below"<<endl;
3231               for(int irow=0; irow < IndiceForColFin.size(); irow++){
3232                 for(int icol=0; icol < IndiceForColFin.size(); icol++){
3233                   std::cout <<"  "<<MesonrecoMatrix1.at(irow).at(icol)<<"  ";
3234                 }
3235                 std::cout <<endl<<endl;
3236               }
3237               */
3238             }
3239 
3240             //possible case  MAT+LBT, MAT+THERM,
3241             //treatment 1 : based on distance.
3242                       if(considering[0].col() > 0 && considering[1].acol() > 0){ //MAT/lbt or therm with color tags + MAT/lbt or therm with color tags
3243                         if(perm2[q2] > 0){
3244                             HH_showerptns[showerquarks[element[1]].par()].acol(considering[0].col());//now color tags from both partons are same
3245                             //also need to set the remaining color tag in showerquarks (if present)
3246                             for(int ishq=0;ishq<showerquarks.num();++ishq){
3247                                 if(!showerquarks[ishq].is_used() && showerquarks[ishq].col()==considering[1].acol()){
3248                     showerquarks[ishq].col(considering[0].col());/*break;*/
3249                   }
3250                             }
3251                             for(int ishq=0;ishq<HH_showerptns.num();++ishq){
3252                                 if(HH_showerptns[ishq].col()==considering[1].acol()){
3253                     HH_showerptns[ishq].col(considering[0].col());/*break;*/
3254                   }
3255                             }
3256                         }else{
3257                 HH_thermal[-element[1]].acol(considering[0].col());
3258               }
3259                       }else if(considering[0].col() > 0){ // MAT + LBT/THERM
3260                         int loc = findcloserepl(considering[1] , perm2[q2], true, true, showerquarks, HH_thermal); // functon to find
3261                         if(loc == 999999999){
3262                             //std::cout <<endl<<"Warning : extra parton used for string repair!!"<<endl;
3263                             HHparton fakep = considering[1]; fakep.id(-fakep.id());  fakep.col(considering[0].col());
3264                 fakep.mass(pythia.particleData.m0(std::abs(fakep.id())));
3265                 fakep.px(0.); fakep.py(0.); fakep.pz(0.);
3266                 fakep.e(fakep.mass());
3267                 fakep.is_fakeparton(true);
3268                             Extraparton.add(fakep);
3269                             //somewhere, we need to make for loop to toss all partons to remnants list.
3270                         }else if(loc < 0){
3271                 HH_thermal[-loc-1].col(considering[0].col());
3272               }else{
3273                 showerquarks[loc-1].col(considering[0].col());
3274                         }
3275                       }else if(considering[1].acol() > 0){ //LBT + MAT
3276                         int loc = findcloserepl(considering[0] , perm1[q1]+1, true, true, showerquarks, HH_thermal);
3277                         if(loc == 999999999){
3278                             //std::cout <<endl<<"Warning : extra parton used for string repair!!"<<endl;
3279                             HHparton fakep = considering[0]; fakep.id(-fakep.id());  fakep.acol(considering[1].acol());
3280                 fakep.mass(pythia.particleData.m0(std::abs(fakep.id())));
3281                 fakep.px(0.); fakep.py(0.); fakep.pz(0.);
3282                 fakep.e(fakep.mass());
3283                 fakep.is_fakeparton(true);
3284                             Extraparton.add(fakep);
3285                             //somewhere, we need to make for loop to toss all partons to remnants list.
3286                         }else if(loc < 0){
3287                 HH_thermal[-loc-1].acol(considering[1].acol());
3288               }else{
3289                 showerquarks[loc-1].acol(considering[1].acol());
3290                         }
3291                       }
3292                   }else if(considering[0].id() < 0 && considering[1].id() > 0){//case of first parton is q-bar and second is q
3293             //std::cout <<endl<<"chosen partons are "<< int(considering[0].id()) << " and " << int(considering[1].id()) << endl <<endl;
3294             //std::cout <<endl<<"and their color tag is "<< int(considering[0].acol()) << " and " << int(considering[1].col()) << endl <<endl;
3295             //std::cout <<"color correction implemented as Follows: "<< considering[0].acol()<<" = "<<considering[1].col()<<endl;
3296 
3297             // Overwrite non-dominant colortags in tempjunctions with dominant ones
3298             // qbar-q case
3299             if(considering[0].acol() != 0 && considering[1].col() != 0){
3300               for(int ijunc=0; ijunc<Tempjunctions.size(); ijunc++){
3301                 if(Tempjunctions.at(ijunc).at(1).at(1) == considering[1].col()){
3302                   Tempjunctions.at(ijunc).at(1).pop_back();
3303                   Tempjunctions.at(ijunc).at(1).push_back(considering[0].acol());
3304                 }
3305                     if(Tempjunctions.at(ijunc).at(2).at(1) == considering[1].col()){
3306                   Tempjunctions.at(ijunc).at(2).pop_back();
3307                   Tempjunctions.at(ijunc).at(2).push_back(considering[0].acol());
3308                 }
3309                     if(Tempjunctions.at(ijunc).at(3).at(1) == considering[1].col()){
3310                   Tempjunctions.at(ijunc).at(3).pop_back();
3311                   Tempjunctions.at(ijunc).at(3).push_back(considering[0].acol());
3312                 }
3313               }
3314             }
3315 
3316             //before changing the tags, revise the MesonrecoMatrix elements!
3317             int coltag1 = considering[0].acol();
3318             int coltag2 = considering[1].col();
3319             if(coltag1 > 0 && coltag2 > 0 && coltag1 <= limit && coltag2 <= limit){
3320               std::vector<int>::iterator I1 = std::find(IndiceForColFin.begin(), IndiceForColFin.end(), coltag1);
3321               std::vector<int>::iterator I2 = std::find(IndiceForColFin.begin(), IndiceForColFin.end(), coltag2);
3322               int loc1 = std::distance(IndiceForColFin.begin(), I1);
3323               int loc2 = std::distance(IndiceForColFin.begin(), I2); //set up for find matrix indices corresponding to the color tags
3324 
3325                         MesonrecoMatrix1.at(loc1).at(loc2) = 1;
3326               MesonrecoMatrix1.at(loc2).at(loc1) = 1; //Matrix revised
3327 
3328                         for(int iM=0;iM<MesonrecoMatrix1[0].size();++iM){
3329                 if(MesonrecoMatrix1[loc1][iM]==1){MesonrecoMatrix1[loc2][iM]=1;}
3330                             if(MesonrecoMatrix1[loc2][iM]==1){MesonrecoMatrix1[loc1][iM]=1;}
3331                             if(MesonrecoMatrix1[iM][loc1]==1){MesonrecoMatrix1[iM][loc2]=1;}
3332                             if(MesonrecoMatrix1[iM][loc2]==1){MesonrecoMatrix1[iM][loc1]=1;}
3333                             if(MesonrecoMatrix1[loc1][iM]==0){MesonrecoMatrix1[loc2][iM]=0;}
3334                             if(MesonrecoMatrix1[loc2][iM]==0){MesonrecoMatrix1[loc1][iM]=0;}
3335                             if(MesonrecoMatrix1[iM][loc1]==0){MesonrecoMatrix1[iM][loc2]=0;}
3336                             if(MesonrecoMatrix1[iM][loc2]==0){MesonrecoMatrix1[iM][loc1]=0;}
3337                         }
3338             }
3339             /*
3340             std::cout <<endl<<"Revised Matrix is same as below"<<endl;
3341             for(int irow=0; irow < IndiceForColFin.size(); irow++){
3342               for(int icol=0; icol < IndiceForColFin.size(); icol++){
3343                 std::cout <<"  "<<MesonrecoMatrix1.at(irow).at(icol)<<"  ";
3344               }
3345               std::cout <<endl<<endl;
3346             }*/
3347                       if(considering[0].acol() > 0 && considering[1].col() > 0){ //MAT + MAT
3348                         if(perm2[q2] > 0){
3349                             HH_showerptns[showerquarks[element[1]].par()].col(considering[0].acol());//now color tags from both partons are same
3350                             //also need to set the remaining color tag in showerquarks (if present)
3351                             for(int ishq=0;ishq<showerquarks.num();++ishq){
3352                                 if(!showerquarks[ishq].is_used() && showerquarks[ishq].acol()==considering[1].col()){
3353                     showerquarks[ishq].acol(considering[0].acol());/*break;*/
3354                   }
3355                             }
3356                             for(int ishq=0;ishq<HH_showerptns.num();++ishq){
3357                                 if(HH_showerptns[ishq].acol()==considering[1].col()){
3358                     HH_showerptns[ishq].acol(considering[0].acol());/*break;*/
3359                   }
3360                             }
3361                         }else{
3362                 HH_thermal[-element[1]].col(considering[0].acol());
3363               }
3364                       }else if(considering[0].acol() > 0){ // MAT + LBT/THERM
3365                         int loc = findcloserepl(considering[1], perm2[q2], true, true, showerquarks, HH_thermal );
3366                         if(loc == 999999999){
3367                             //std::cout <<endl<<"Warning : extra parton used for string repair!!"<<endl;
3368                             HHparton fakep = considering[1]; fakep.id(-fakep.id());  fakep.acol(considering[0].acol());
3369                 fakep.mass(pythia.particleData.m0(std::abs(fakep.id())));
3370                 fakep.px(0.); fakep.py(0.); fakep.pz(0.);
3371                 fakep.e(fakep.mass());
3372                 fakep.is_fakeparton(true);
3373                             Extraparton.add(fakep);
3374                             //somewhere, we need to make for loop to toss all partons to remnants list.
3375                         }else if (loc > 0){
3376                 showerquarks[loc-1].acol(considering[0].acol());
3377               }else if(loc < 0){
3378                 HH_thermal[-loc-1].acol(considering[0].acol());
3379               }
3380                       }
3381                       else if(considering[1].col() > 0){ //LBT + MAT
3382                           int loc = findcloserepl(considering[0], perm1[q1]+1, true, true, showerquarks, HH_thermal );
3383                           if(loc == 999999999){
3384                             //std::cout <<endl<<"Warning : extra parton used for string repair!!"<<endl;
3385                             HHparton fakep = considering[0]; fakep.id(-fakep.id());  fakep.col(considering[1].col());
3386                 fakep.mass(pythia.particleData.m0(std::abs(fakep.id())));
3387                 fakep.px(0.); fakep.py(0.); fakep.pz(0.);
3388                 fakep.e(fakep.mass());
3389                 fakep.is_fakeparton(true);
3390                             Extraparton.add(fakep);
3391                             //somewhere, we need to make for loop to toss all partons to remnants list.
3392                           }else if (loc > 0){
3393                 showerquarks[loc-1].col(considering[1].col());
3394               }else if(loc < 0){
3395                 HH_thermal[-loc-1].col(considering[1].col());
3396               }
3397                     }
3398             //now color tags from both partons are same
3399           }
3400 
3401                     //now we're forming the hadron
3402                     HHhadron formedhadron;
3403                     //setting the hadron values: is a recombined hadron, mass, and parents - setting the par3 flag to 999999 to denote the lack of a 3rd parent parton
3404                     formedhadron.is_recohad(true); formedhadron.mass( p_MCM[0].t() + p_MCM[1].t() );
3405                     //formedhadron.par1 = element[0]; formedhadron.par2 = element[1]; formedhadron.par3 = 999999;
3406                     formedhadron.add_par(showerquarks[element[0]].par());
3407                     if(perm2[q2]>0){formedhadron.add_par(showerquarks[element[1]].par());}else{formedhadron.add_par(element[1]);}
3408 
3409                     //now setting if meson is in excited state
3410                     if(angular_qnum + radial_qnum > 0){formedhadron.is_excited(true);}
3411 
3412                     //setting if there are any thermal partons used to make the hadron: (setting the '0' thermal parent to -99999 so that it doesn't conflict with '0' shower parton)
3413                     if(     perm2[q2]>0){/*is sh-sh*/ formedhadron.is_shsh(true);}
3414                     else if(perm2[q2]<0){/*is sh-th*/ formedhadron.is_shth(true); if(element[1] == 0){formedhadron.parents[1] = -99999;}}
3415 
3416                     //setting hadron position and momentum vectors
3417                     Pmeson.Set(Pmeson.x(),Pmeson.y(),Pmeson.z(),sqrt(Pmeson.x()*Pmeson.x() + Pmeson.y()*Pmeson.y() + Pmeson.z()*Pmeson.z() + formedhadron.mass()*formedhadron.mass()));
3418                     formedhadron.pos(pos_lab); formedhadron.P(Pmeson);
3419 
3420                     //setting hadron color tags (for tracing colors of the constituent partons)
3421                     //will need to update to reflect color tags given to random (thermal/lbt) partons [**]
3422                     if(considering[0].id()>0){formedhadron.add_col(considering[0].col()); formedhadron.add_col(considering[1].acol());}
3423                     else{formedhadron.add_col(considering[1].col()); formedhadron.add_col(considering[0].acol());}
3424 
3425                     //need to choose *what* hadron we've formed... base this on the parton id's, mass, & if excited
3426                     set_meson_id(considering, formedhadron, angular_qnum, radial_qnum);
3427 
3428                     //need to add the hadron to the collection
3429                     HH_hadrons.add(formedhadron);
3430 
3431                     //now that we've formed the hadron, need to set ALL (both) the 'considering' flags to used
3432                                     showerquarks[element[0]].status(1); showerquarks[element[0]].is_used(true);
3433                     if(perm2[q2]>0){showerquarks[element[1]].status(1); showerquarks[element[1]].is_used(true);}
3434                     else{            HH_thermal[-element[1]].status(1);  HH_thermal[-element[1]].is_used(true);}
3435 
3436                     //now that we've formed the hadron, break to first loop here!
3437                     madehadron = true; considering.clear();
3438                     break;
3439                 }
3440             }
3441 
3442             //if we've formed a hadron - break to first loop
3443             if(madehadron){break;}
3444 
3445             //since we CAN'T form a baryon on this try, need to revert the second quark 'considering' used flag
3446             if(perm2[q2]>0){showerquarks[element[1]].status(0);}
3447             else{            HH_thermal[-element[1]].status(0);}
3448 
3449             //and remove the second entry in considering (putting in if statement in case we tried and failed to make a hadron;
3450             considering.partons.pop_back();
3451         }
3452         //if we've formed a hadron - continue to next parton in first loop...
3453         if(madehadron){continue;}
3454 
3455         //since we've not formed a hadron with the first quark, need to revert the first quark 'considering' used flag
3456         //only need to reset these for shower quarks as the first quark cannot be a thermal quark
3457         //and remove the first(only) entry in considering
3458         showerquarks[element[0]].status(0); considering.partons.pop_back();
3459     }
3460 
3461     //all possibilities have been considered, all used quark flags for showerquarks are set appropriately
3462     //time for cleanup
3463 
3464     //set the used quarks in the original shower to reflect that they were used in reco module and that they were actually used
3465     //set the fully used gluons in the original shower to reflect that they were used in reco module and that they were actually used
3466     //set the partially used gluons in the original shower to reflect that they were used in reco module and that they were actually used
3467     //give used quarks and fully used gluons a status of '1'; give partially used gluons a status of '-1'
3468     //stick all unused quarks and 'completely' unused gluons into remnants (make sure to set the parents to the original shower partons appropriately)
3469     //write updated string information into shower, so that it is set properly in remnants
3470     //for the thermal array, all the used flags should already be set (and have a status of '1')
3471     //if this is used in a loop (as the original version should be doing) - those will have to be reset before reuse
3472     //otherwise, this is perfect for medium feedback
3473 
3474     //using quarks in showerquarks to set the flags appropriately for partons in shower
3475     for(int i=0; i<showerquarks.num(); ++i){
3476         //if we have a quark in the original shower
3477         if((std::abs(HH_showerptns[showerquarks[i].par()].id()) <= 5) && (showerquarks[i].is_used())){
3478             HH_showerptns[showerquarks[i].par()].is_used(true);
3479       HH_showerptns[showerquarks[i].par()].status(1);
3480       HH_showerptns[showerquarks[i].par()].used_reco(true);
3481         }
3482         //if this quark is from a split gluon in the original shower
3483         else if(std::abs(HH_showerptns[showerquarks[i].par()].id()) == 21 && showerquarks[i].is_used()){
3484             //if this is the first used quark in a splitting, set the parent gluon to used, and status of -1
3485             if(HH_showerptns[showerquarks[i].par()].status() == -99){
3486                 HH_showerptns[showerquarks[i].par()].status(-1);
3487         HH_showerptns[showerquarks[i].par()].is_used(true);
3488         HH_showerptns[showerquarks[i].par()].used_reco(true);
3489             }
3490             //if this is the second (last) used quark in a splitting, set the status to 1
3491             else if(HH_showerptns[showerquarks[i].par()].status() == -1){
3492         HH_showerptns[showerquarks[i].par()].status(1);
3493       }
3494             //remove this check if it never throws.
3495             else{JSWARN << "SOMETHING HAS GONE VERY WRONG WITH REFORMING GLUON IN POS: " << showerquarks[i].par(); int val; showerquarks[i].par(0);}
3496         }
3497     }
3498     //need to run back through shower; if there are any gluons that didn't get used at all in the shower - restore them (and output to remnants below)
3499     for(int i=0; i<HH_showerptns.num(); ++i){
3500     if(HH_showerptns[i].status() == -99){
3501       HH_showerptns[i].is_decayedglu(false);
3502       HH_showerptns[i].status(0);
3503     }
3504   }
3505 
3506     //need to update string information in shower from showerquarks
3507     for(int i=0; i<HH_showerptns.num(); ++i){
3508     if(!HH_showerptns[i].is_used()){
3509           for(int j=0; j<showerquarks.num(); ++j){
3510         if(showerquarks[j].par() == i && !showerquarks[j].is_used()){
3511                 HH_showerptns[i].string_id(   showerquarks[j].string_id());
3512                 HH_showerptns[i].is_strendpt( showerquarks[j].is_strendpt());
3513                 HH_showerptns[i].pos_str(     showerquarks[j].pos_str());
3514                 HH_showerptns[i].endpt_id(    showerquarks[j].endpt_id());
3515                 break;
3516             }
3517       }
3518       }
3519   }
3520     //now all the partons in shower have had flags appropriately set; the 'partially' used gluons have a status of -1
3521 
3522   //TODO: here we need new function to find thermal sibling for gluon
3523   //sol 1 : gluon loops.
3524   //sol 2 : decay gluon find pairs.{concern : energy conservation violated}
3525   //sol 3 : find two theraml siblings for gluon. declare fincloserepl twice. first pick quark and antiquarks to the 2nd.--> this is chosen
3526     for(int i = 0; i < HH_showerptns.num(); i++){
3527         if(HH_showerptns[i].is_used()){continue;}
3528         if(HH_showerptns[i].id() == 21 && HH_showerptns[i].col() == 0 && HH_showerptns[i].acol() == 0){
3529             int sel_out[2] = { 0 , 0 };
3530             findcloserepl_glu(HH_showerptns[i], i+1, true, true, HH_showerptns, HH_thermal, sel_out);
3531             if(sel_out[0] == 999999999 || sel_out[1] == 999999999){
3532                 HHparton fakeg = HH_showerptns[i]; fakeg.id(21);  fakeg.acol(++maxtag); fakeg.col(++maxtag);
3533         fakeg.mass(1e-6);
3534                 double fake_pT = (p_fake >= 1.) ? 0.282842712474619 : 0.; double fake_phi = 2. * 3.14159265358979 * ran();
3535                 fakeg.px(fake_pT * cos(fake_phi)); fakeg.py(fake_pT * sin(fake_phi));
3536         fakeg.pz(0.);
3537                 fakeg.e(std::sqrt(fakeg.px()*fakeg.px() + fakeg.py()*fakeg.py() + fakeg.pz()*fakeg.pz() + fakeg.mass()*fakeg.mass()));
3538                 fakeg.orig(-1); fakeg.is_remnant(true);
3539         fakeg.is_fakeparton(true);
3540                 Extraparton.add(fakeg); HH_showerptns[i].col(fakeg.acol()); HH_showerptns[i].acol(fakeg.col());
3541             }else if(sel_out[0] > 0){
3542         HH_showerptns[sel_out[0]-1].col(++maxtag);
3543         HH_showerptns[i].acol(maxtag);
3544       }else if(sel_out[0] < 0){
3545         HH_thermal[-sel_out[0]-1].col(++maxtag);
3546         HH_showerptns[i].acol(maxtag);
3547       }
3548 
3549             if(sel_out[1] > 0 && sel_out[1] != 999999999 && sel_out[0] != 999999999){
3550         HH_showerptns[sel_out[1]-1].acol(++maxtag);
3551         HH_showerptns[i].col(maxtag);
3552       }else if(sel_out[1] < 0 && sel_out[1] != 999999999 && sel_out[0] != 999999999){
3553         HH_thermal[-sel_out[1]-1].acol(++maxtag);
3554         HH_showerptns[i].col(maxtag);
3555       }
3556         }else if(HH_showerptns[i].id() == 21 && (HH_showerptns[i].col() == 0 || HH_showerptns[i].acol() == 0)){ //gluon that needs a single quark to fix
3557             if(HH_showerptns[i].col() == 0){
3558                 HH_showerptns[i].id(1); //need to temporarily pretend gluon is a quark, swap back id after...
3559                 int loc = findcloserepl(HH_showerptns[i], i+1, true, true, HH_showerptns, HH_thermal );
3560                 HH_showerptns[i].id(21);
3561                 if(loc == 999999999){
3562                     double fid = (ran() > 0.5) ? -1 : -2;
3563                     HHparton fakep = HH_showerptns[i]; fakep.id(fid);  fakep.acol(++maxtag);
3564                     double dir = (ran() < 0.5) ? 1. : -1.; double fake_pT = (p_fake >= 1.) ? 0.282842712474619 : 0.; double fake_phi = 2. * 3.14159265358979 * ran();
3565                     fakep.px(fake_pT * cos(fake_phi)); fakep.py(fake_pT * sin(fake_phi));
3566           if (number_p_fake == 0 || number_p_fake == 2){
3567             fakep.pz(-p_fake);
3568           } else if (number_p_fake == 1 || number_p_fake == 3) {
3569             fakep.pz(p_fake);
3570           } else {fakep.pz(0.);}
3571           number_p_fake++;
3572                     fakep.e(std::sqrt(fakep.px()*fakep.px() + fakep.py()*fakep.py() + fakep.pz()*fakep.pz() + fakep.mass()*fakep.mass()));
3573                     fakep.orig(-1); fakep.is_remnant(true);
3574           fakep.is_fakeparton(true);
3575                     Extraparton.add(fakep);
3576                 }
3577                 else if (loc > 0){HH_showerptns[loc - 1].acol(++maxtag); }
3578                 else if(loc < 0){HH_thermal[-loc - 1].acol(++maxtag); }
3579 
3580                 HH_showerptns[i].col(maxtag);
3581             }else if(HH_showerptns[i].acol() == 0){
3582                 HH_showerptns[i].id(-1); //need to temporarily pretend gluon is an antiquark, swap back id after...
3583                 int loc = findcloserepl(HH_showerptns[i], i+1, true, true, HH_showerptns, HH_thermal );
3584                 HH_showerptns[i].id(21);
3585                 if(loc == 999999999){
3586           double fid = (ran() > 0.5) ? 1 : 2;
3587                     HHparton fakep = HH_showerptns[i]; fakep.id(fid);  fakep.col(++maxtag);
3588                     double dir = (ran() < 0.5) ? 1. : -1.; double fake_pT = (p_fake >= 1.) ? 0.282842712474619 : 0.; double fake_phi = 2. * 3.14159265358979 * ran();
3589                     fakep.px(fake_pT * cos(fake_phi)); fakep.py(fake_pT * sin(fake_phi));
3590           if (number_p_fake == 0 || number_p_fake == 2){
3591             fakep.pz(-p_fake);
3592           } else if (number_p_fake == 1 || number_p_fake == 3) {
3593             fakep.pz(p_fake);
3594           } else {fakep.pz(0.);}
3595           number_p_fake++;
3596                     fakep.e(std::sqrt(fakep.px()*fakep.px() + fakep.py()*fakep.py() + fakep.pz()*fakep.pz() + fakep.mass()*fakep.mass()));
3597                     fakep.orig(-1); fakep.is_remnant(true);
3598           fakep.is_fakeparton(true);
3599                     Extraparton.add(fakep);
3600                 }
3601                 else if (loc > 0){HH_showerptns[loc - 1].col(++maxtag); }
3602                 else if(loc < 0){HH_thermal[-loc - 1].col(++maxtag); }
3603 
3604                 HH_showerptns[i].acol(maxtag);
3605             }
3606         }else if(HH_showerptns[i].id() > 0 && HH_showerptns[i].col() == 0){
3607             int loc = findcloserepl(HH_showerptns[i], i+1, true, true, HH_showerptns, HH_thermal );
3608             if(loc == 999999999){
3609         double fid = (ran() > 0.5) ? -1 : -2;
3610                 HHparton fakep = HH_showerptns[i]; fakep.id(fid);  fakep.acol(++maxtag);
3611                 double dir = (ran() < 0.5) ? 1. : -1.; double fake_pT = (p_fake >= 1.) ? 0.282842712474619 : 0.; double fake_phi = 2. * 3.14159265358979 * ran();
3612                 fakep.px(fake_pT * cos(fake_phi)); fakep.py(fake_pT * sin(fake_phi));
3613         if (number_p_fake == 0 || number_p_fake == 2){
3614           fakep.pz(-p_fake);
3615         } else if (number_p_fake == 1 || number_p_fake == 3) {
3616           fakep.pz(p_fake);
3617         } else {fakep.pz(0.);}
3618         number_p_fake++;
3619                 fakep.e(std::sqrt(fakep.px()*fakep.px() + fakep.py()*fakep.py() + fakep.pz()*fakep.pz() + fakep.mass()*fakep.mass()));
3620                 fakep.orig(-1); fakep.is_remnant(true);
3621         fakep.is_fakeparton(true);
3622                 Extraparton.add(fakep);
3623             }
3624             else if (loc > 0){HH_showerptns[loc - 1].acol(++maxtag); }
3625             else if(loc < 0){HH_thermal[-loc - 1].acol(++maxtag); }
3626 
3627             HH_showerptns[i].col(maxtag);
3628         }else if(HH_showerptns[i].id() < 0 && HH_showerptns[i].acol() == 0){
3629             int loc = findcloserepl(HH_showerptns[i], i+1, true, true, HH_showerptns, HH_thermal );
3630             if(loc == 999999999){
3631         double fid = (ran() > 0.5) ? 1 : 2;
3632                 HHparton fakep = HH_showerptns[i]; fakep.id(fid);  fakep.col(++maxtag);
3633                 double dir = (ran() < 0.5) ? 1. : -1.; double fake_pT = (p_fake >= 1.) ? 0.282842712474619 : 0.; double fake_phi = 2. * 3.14159265358979 * ran();
3634                 fakep.px(fake_pT * cos(fake_phi)); fakep.py(fake_pT * sin(fake_phi));
3635         if (number_p_fake == 0 || number_p_fake == 2){
3636           fakep.pz(-p_fake);
3637         } else if (number_p_fake == 1 || number_p_fake == 3) {
3638           fakep.pz(p_fake);
3639         } else {fakep.pz(0.);}
3640         number_p_fake++;
3641                 fakep.e(std::sqrt(fakep.px()*fakep.px() + fakep.py()*fakep.py() + fakep.pz()*fakep.pz() + fakep.mass()*fakep.mass()));
3642                 fakep.orig(-1); fakep.is_remnant(true);
3643         fakep.is_fakeparton(true);
3644                 Extraparton.add(fakep);
3645             }
3646             else if (loc > 0){HH_showerptns[loc - 1].col(++maxtag); }
3647             else if(loc < 0){HH_thermal[-loc - 1].col(++maxtag); }
3648 
3649             HH_showerptns[i].acol(maxtag);
3650         }
3651     }
3652     //sticking all unused partons into remnants; keeping order intact (a partially used gluon is replaced with it's unused quark)
3653     for(int i=0; i < HH_showerptns.num(); ++i){
3654         //if unused parton, write into remnants
3655         if(HH_showerptns[i].status() == 0){
3656       HH_remnants.add(HH_showerptns[i]);
3657       HH_remnants[HH_remnants.num() - 1].par(i);
3658       HH_showerptns[i].is_remnant(true);
3659     }
3660         //if 'partially' used gluon, write unused daughter quark into remnants
3661         else if(HH_showerptns[i].status() == -1){
3662             //finding the unused quark for this gluon and adding it to remnants (have to loop over as we only keep track of parents, not daughters)
3663             for(int j=0; j<showerquarks.num(); ++j){if(showerquarks[j].par() == i && !showerquarks[j].is_used()){
3664         if(showerquarks[j].col() == 0 && showerquarks[j].id() > 0){ //quark with zero col tag is left,
3665           int loc = findcloserepl(showerquarks[j], j+1, true, true, HH_showerptns, HH_thermal );
3666           if(loc == 999999999){
3667             double fid = (ran() > 0.5) ? -1 : -2;
3668             HHparton fakep = showerquarks[j]; fakep.id(fid);  fakep.acol(++maxtag);
3669             double dir = (ran() < 0.5) ? 1. : -1.; double fake_pT = (p_fake >= 1.) ? 0.282842712474619 : 0.; double fake_phi = 2. * 3.14159265358979 * ran();
3670             fakep.px(fake_pT * cos(fake_phi)); fakep.py(fake_pT * sin(fake_phi));
3671             if (number_p_fake == 0 || number_p_fake == 2){
3672               fakep.pz(-p_fake);
3673             } else if (number_p_fake == 1 || number_p_fake == 3) {
3674               fakep.pz(p_fake);
3675             } else {fakep.pz(0.);}
3676             number_p_fake++;
3677             fakep.e(std::sqrt(fakep.px()*fakep.px() + fakep.py()*fakep.py() + fakep.pz()*fakep.pz() + fakep.mass()*fakep.mass()));
3678             fakep.orig(-1); fakep.is_remnant(true);
3679             fakep.is_fakeparton(true);
3680             Extraparton.add(fakep);
3681           }
3682           else if (loc > 0){HH_showerptns[loc - 1].acol(++maxtag); }
3683           else if(loc < 0){HH_thermal[-loc - 1].acol(++maxtag); }
3684 
3685           showerquarks[j].col(maxtag);
3686         }else if(showerquarks[j].acol() == 0 && showerquarks[j].id() < 0){ //antiquark with zero col tag is left,
3687           int loc = findcloserepl(showerquarks[j], j+1, true, true, HH_showerptns, HH_thermal );
3688           if(loc == 999999999){
3689             double fid = (ran() > 0.5) ? 1 : 2;
3690             HHparton fakep = showerquarks[j]; fakep.id(fid);  fakep.col(++maxtag);
3691             double dir = (ran() < 0.5) ? 1. : -1.; double fake_pT = (p_fake >= 1.) ? 0.282842712474619 : 0.; double fake_phi = 2. * 3.14159265358979 * ran();
3692             fakep.px(fake_pT * cos(fake_phi)); fakep.py(fake_pT * sin(fake_phi));
3693             if (number_p_fake == 0 || number_p_fake == 2){
3694               fakep.pz(-p_fake);
3695             } else if (number_p_fake == 1 || number_p_fake == 3) {
3696               fakep.pz(p_fake);
3697             } else {fakep.pz(0.);}
3698             number_p_fake++;
3699             fakep.e(std::sqrt(fakep.px()*fakep.px() + fakep.py()*fakep.py() + fakep.pz()*fakep.pz() + fakep.mass()*fakep.mass()));
3700             fakep.orig(-1); fakep.is_remnant(true);
3701             fakep.is_fakeparton(true);
3702             Extraparton.add(fakep);
3703           }
3704           else if (loc > 0){HH_showerptns[loc - 1].col(++maxtag); }
3705           else if(loc < 0){HH_thermal[-loc - 1].col(++maxtag); }
3706 
3707           showerquarks[j].acol(maxtag);
3708         }
3709 
3710         HH_remnants.add(showerquarks[j]); break;
3711       }}
3712             HH_showerptns[i].is_remnant(true);
3713         }
3714     }
3715 
3716     //appending the thermal partons used in the string repair functionality into remnants
3717     for(int i=0; i < HH_thermal.num(); ++i){
3718         //if this thermal parton is ... then add it to the remnants collection
3719         if(HH_thermal[i].is_used()){
3720       HH_thermal[i].status(1);
3721       HH_thermal[i].used_reco(true);
3722       continue;
3723     }
3724         if(HH_thermal[i].col() > 0 || HH_thermal[i].acol() > 0){
3725       //std::cout << "Thermal parton added to remnants: " << HH_thermal[i].id() << "," << HH_thermal[i].col() << "," << HH_thermal[i].acol() << std::endl;
3726       HH_remnants.add(HH_thermal[i]);
3727       HH_remnants[HH_remnants.num() - 1].par(-i-1);
3728       HH_thermal[i].is_remnant(true);
3729       HH_thermal[i].is_used(true);
3730     }
3731     }
3732 
3733   for(int i = 0; i < Extraparton.num(); ++i ){
3734     HH_remnants.add(Extraparton[i]);
3735     Extraparton[i].is_used(true); // use the extrapartons during hadronizations of negative partons (background subtraction)
3736 
3737     if(Extraparton[i].id() == 21){
3738       HHparton fakep1 = Extraparton[i];
3739       fakep1.id(1); fakep1.acol(0);
3740       fakep1.px(fakep1.px()/2.); fakep1.py(fakep1.py()/2.); fakep1.pz(fakep1.pz()/2.); fakep1.mass(xmq);
3741       fakep1.e(std::sqrt(fakep1.px()*fakep1.px()+fakep1.py()*fakep1.py()+fakep1.pz()*fakep1.pz()+fakep1.mass()*fakep1.mass()));
3742 
3743       HHparton fakep2 = Extraparton[i];
3744       fakep2.id(-1); fakep2.col(0);
3745       fakep2.px(fakep2.px()/2.); fakep2.py(fakep2.py()/2.); fakep2.pz(fakep2.pz()/2.); fakep2.mass(xmq);
3746       fakep2.e(std::sqrt(fakep2.px()*fakep2.px()+fakep2.py()*fakep2.py()+fakep2.pz()*fakep2.pz()+fakep2.mass()*fakep2.mass()));
3747 
3748       HH_recomb_extrapartons.add(fakep1);
3749       HH_recomb_extrapartons.add(fakep2);
3750     } else {
3751       HH_recomb_extrapartons.add(Extraparton[i]);
3752     }
3753   }
3754 
3755     //hadrons have been recombined, and output to hadron collection
3756     //remnants have been collected, and output to remnant collection
3757     //shower partons have all been updated appropriately
3758     //thermal partons have all been updated appropriately - make sure that the thermal partons are reset before the recomb module is called again...
3759 
3760   //end of recombination routine
3761 }
3762 
3763 //sets id of formed baryon based on quark content, mass of quark system, and if the baryon formed into an excited state
3764 void HybridHadronization::set_baryon_id(parton_collection& qrks, HHhadron& had){
3765 
3766     //assigning quark_ids in descending order to construct baryon id
3767     int id[3] = {qrks[0].id(), qrks[1].id(), qrks[2].id()};
3768   std::sort(id, id + 3, [](int a, int b) { return std::abs(a) > std::abs(b); });
3769 
3770   /*//http://pdg.lbl.gov/2017/listings/contents_listings.html
3771     double mdelta, msigma, mlambda, mxi, mdelE, msigmaE, mxiE, momega;
3772     mdelta  = 1.232;
3773     msigma  = 1.190;
3774     msigmaE = 1.382;
3775     mlambda = 1.115;
3776     mxi     = 1.315;
3777     mxiE    = 1.530;
3778     momega  = 1.672;
3779   //    ^^^^^ MIGHT NOT NEED MASSES BUT KEEP FOR NOW ^^^^^^
3780   */
3781     //id and mass list:
3782     //ground state: (111, 222, 333 configurations prohibited...)
3783     //  2212, 2112 - .938  p,n
3784     //  3222, 3212, 3112 - 1.190   sigma;  3122 - 1.115 lambda
3785     //  3322, 3312 - 1.315  xi
3786     //
3787     //excited:
3788     //  2224, 2214, 2114, 1114 - 1.232  delta
3789     //  3224, 3214, 3114 - 1.190   sigma;
3790     //  3324, 3314 - 1.315  xi
3791     //  3334 - 1.672 omega
3792   //    ^^^^^ MIGHT NOT NEED BUT KEEP FOR NOW ^^^^^^
3793 
3794     if(id[0]==id[1] && id[0]==id[2]){had.id( 1000*std::abs(id[0]) + 100*std::abs(id[1]) + 10*std::abs(id[2])+4 );}  // J=3/2 only
3795     else if(id[0]==id[1] || id[0]==id[2] || id[1]==id[2]){
3796         if(ran()>0.333){had.id( 1000*std::abs(id[0]) + 100*std::abs(id[1]) + 10*std::abs(id[2])+4 );}  // J=3/2
3797         else{           had.id( 1000*std::abs(id[0]) + 100*std::abs(id[1]) + 10*std::abs(id[2])+2 );}
3798     }
3799     else{
3800         double prb = ran();
3801         if(     prb>0.333){had.id( 1000*std::abs(id[0]) + 100*std::abs(id[1]) + 10*std::abs(id[2])+4 );}  // J=3/2
3802         else if(prb>0.166){had.id( 1000*std::abs(id[0]) + 100*std::abs(id[1]) + 10*std::abs(id[2])+2 );}  // J=1/2 higher mass
3803         else{              had.id( 1000*std::abs(id[0]) + 10*std::abs(id[1]) + 100*std::abs(id[2])+2 );}  // J=1/2 lower mass
3804     }   // note the swap of quark index in last line
3805 
3806     // This would be how to make excited N, Delta and Lambda. RIGHT NOW DISABLED IN FIRST IF STATEMENT
3807     //there are no excited baryon codes of this form; there are only spin excited states in PYTHIA's ParticleData class
3808   //if(false && had.is_excited){
3809   //    if(had.id == 2212 || had.id == 2112 || had.id == 2214 || had.id == 2114 || had.id == 2224 || had.id ==1114 || had.id == 3122){
3810   //        had.id += 100000;  // This needs to be adjusted to make the actual excited baryon codes
3811   //    }
3812   //}
3813 
3814   had.id(had.id() * (id[0] < 0 ? -1 : 1));
3815     return;
3816 }
3817 
3818 //sets id of formed meson based on quark content, mass of quark system, and if the meson formed into an excited state
3819 void HybridHadronization::set_meson_id(parton_collection& qrks, HHhadron& had, int l, int k){
3820 
3821     //assigning quark_ids in descending order to construct meson id
3822     int id[2] = {qrks[0].id(), qrks[1].id()};
3823     if(std::abs(qrks[1].id()) > std::abs(qrks[0].id())){
3824     std::swap(id[0], id[1]);
3825   }
3826 
3827   //  Don't need the following any more
3828   //    double mass_pi0, mass_eta, mass_omegam, mass_etap, mass_phi; //mass_rho;
3829   //    mass_pi0    = 0.1349770;
3830   //    mass_eta    = 0.547862;
3831   //    mass_rho    = 0.7690;
3832   //    mass_omegam = 0.78265;
3833   //    mass_etap   = 0.95778;
3834   //    mass_phi    = 1.019460;
3835   //// MASSES ABOVE NOT REALLY NEEDED IN SIMPLE QUARK MODEL BASED APPROACH
3836 
3837     int baseid = 0;
3838 
3839   // Determine spin quantum number statistically
3840   int spin_qnum = (ran() > 0.25) ? 1 : 0;
3841 
3842   // Determine total angular momentum statistically
3843     int j_qnum = spin_qnum;
3844     if(l > 0 && spin_qnum == 1){
3845         double random = ran();
3846 
3847         if((2.*l-1.)/(3.*(2.*l+1.)) >= random){j_qnum = l - 1;}
3848         else if(1./3. + (2.*l-1.)/(3.*(2.*l+1.)) >= random){j_qnum = l;}
3849         else{j_qnum = l + 1;}
3850     }
3851     else if (spin_qnum == 0){j_qnum = l;}
3852 
3853   // All meson quantum numbers are now known
3854 
3855   int basesign = 1;
3856     //if isospin I3=0
3857     if(id[0] == -id[1]){
3858         if(ran() > 0.25){   //spin triplet
3859             if(std::abs(id[0])==5){baseid = 550;}                   // Upsilon
3860             if(std::abs(id[0])==4){baseid = 440;}                   // J/psi
3861             if(std::abs(id[0])==3){baseid = 330;}                   // phi
3862             if((std::abs(id[0])==1) || (std::abs(id[0]) == 2)){
3863                 if(ran()>0.5){baseid = 220;} else{baseid = 110;}
3864             }   // omega and rho
3865         }
3866         else{   // spin singlet
3867             if(std::abs(id[0])==5){baseid = 550; }                  // etaB
3868             if(std::abs(id[0])==4){baseid = 440; }                  // etac
3869             if(std::abs(id[0])==3){if(ran()>0.666){baseid = 330;} else{baseid = 220;}}  // eta' and eta
3870             if(std::abs(id[0])<3){
3871                 double prb = ran();
3872                 if(prb>0.5){baseid = 110;}                          // pi0
3873                 else if(prb>0.333){baseid = 220;}               // eta
3874                 else{baseid = 330;}                                     // eta'
3875             }
3876         }
3877     }
3878     // if isospin I3 not 0
3879     else{
3880         baseid = 100*std::abs(id[0])+10*std::abs(id[1]);
3881         if(id[0]%2 == 0){basesign = 2*std::signbit(-id[0])-1;}
3882         else{            basesign = 2*std::signbit( id[0])-1;}
3883     }
3884 
3885   // Put everything together: first digit (from the right)
3886   if(j_qnum < 5){baseid += 2*j_qnum + 1;}
3887     else{baseid += 8;}
3888 
3889   // 5th digit
3890   if(l > 0 && spin_qnum == 0){baseid += 10000;}
3891     else if(l > 0 && spin_qnum == 1 && l == j_qnum){baseid += 20000;}
3892     else if(l > 1 && spin_qnum == 1 && l == j_qnum + 1){baseid += 30000;}
3893     else if(l == 1 && spin_qnum == 1 && l == j_qnum + 1){baseid += 10000;}
3894 
3895   // 6th digit
3896     if(k < 10){baseid += k*100000;}
3897     else{baseid += 900000;}
3898 
3899   // If we don't want Goldstone bosons convert them to vector mesons here
3900   if(!goldstonereco){
3901     if(baseid == 211){baseid = 213;} //fixed pi+- -> rho+-
3902       if(baseid == 311){baseid = 313;} // fixed for K+- -> K*+-
3903       if(baseid == 321){baseid = 323;} // fixed for K0 -> K*0
3904       if(baseid == 111){baseid = 113;} //fixed for pi0 -> rho0
3905   }
3906 
3907   baseid *= basesign;
3908 
3909   had.id( baseid );
3910     return;
3911 }
3912 
3913 //gluon decay function
3914 void HybridHadronization::gluon_decay(HHparton& glu, parton_collection& qrks){
3915 
3916     HHparton q1, q2;
3917     //these are placeholders - might want to instead use values directly from partons...
3918     double qmass, glu_e;
3919 
3920     //if set to already be not on-shell, but not initially set!
3921     //glu.mass = sqrt(glu.e()*glu.e() - glu.px()*glu.px() - glu.py()*glu.py() - glu.pz()*glu.pz());
3922     //glu_e = glu.e();
3923     glu_e = sqrt(glu.mass()*glu.mass() + glu.px()*glu.px() + glu.py()*glu.py() + glu.pz()*glu.pz());
3924 
3925     //choosing qqbar ids (u, d, or s)
3926     //assuming that xms >= xmq (bad things *could* happen if not...)
3927     if(glu.mass() > 2.*xms){
3928         //******** ratio = Gamma(g->ssbar)/Gamma(g->uubar, ddbar) ******
3929         double ratio = 0.5*sqrt((glu.mass()*glu.mass()-4.*xms*xms)/(glu.mass()*glu.mass()-4.*xmq*xmq))*((glu.mass()*glu.mass()+2.*xms*xms)/(glu.mass()*glu.mass()+2.*xmq*xmq));
3930         double prob = ran();
3931         if(prob <= ratio/(1.+ratio)){qmass = xms; q1.id(3); q2.id(-3); q1.mass(xms); q2.mass(xms);}
3932         else if((prob > ratio/(1.+ratio)) && (prob <= (0.5+ratio)/(1.+ratio))){qmass = xmq; q1.id(1); q2.id(-1); q1.mass(xmq); q2.mass(xmq);}
3933         else{ /*if (prob > (0.5+ratio)/(1.+ratio))*/ qmass = xmq; q1.id(2); q2.id(-2); q1.mass(xmq); q2.mass(xmq);}
3934     }else{
3935         double prob = ran();
3936         if(prob <= 0.5){qmass = xmq; q1.id(1); q2.id(-1); q1.mass(xmq); q2.mass(xmq);}
3937         else{           qmass = xmq; q1.id(2); q2.id(-2); q1.mass(xmq); q2.mass(xmq);}
3938     }
3939 
3940     //gluon velocity
3941     FourVector Betag;
3942     Betag.Set(-glu.px()/glu_e,-glu.py()/glu_e,-glu.pz()/glu_e,0.);
3943     double sum2 = Betag.x()*Betag.x() + Betag.y()*Betag.y() + Betag.z()*Betag.z();
3944     if(sum2 < 1.){Betag.Set(Betag.x(),Betag.y(),Betag.z(),1./sqrt(1.-sum2));}
3945 
3946     //setting the q-qbar momenta, starting in gluon rest frame
3947     FourVector Pq_CM, Pq1, Pq2;
3948     double pq = (glu.mass() > 2.*qmass) ? sqrt(glu.mass()*glu.mass()/4. - qmass*qmass) : 0.;
3949     double theta = acos(1.-2.*ran()); double phi = 2*pi*ran();
3950     Pq_CM.Set(pq*sin(theta)*cos(phi),pq*sin(theta)*sin(phi),pq*cos(theta),sqrt(qmass*qmass+pq*pq));
3951     Pq1 = HHboost(Betag,Pq_CM);
3952     Pq_CM.Set(-Pq_CM.x(),-Pq_CM.y(),-Pq_CM.z(),Pq_CM.t());
3953     Pq2 = HHboost(Betag,Pq_CM);
3954     q1.P(Pq1); q2.P(Pq2);
3955   q1.col(glu.col()); q2.acol(glu.acol());
3956 
3957   // propagate quarks
3958   FourVector position1;
3959   FourVector position2;
3960   position1.Set(glu.x()+(Pq1.x() / qmass)*part_prop,glu.y()+(Pq1.y() / qmass)*part_prop,glu.z()+(Pq1.z() / qmass)*part_prop,glu.x_t()+part_prop);
3961   position2.Set(glu.x()+(Pq2.x() / qmass)*part_prop,glu.y()+(Pq2.y() / qmass)*part_prop,glu.z()+(Pq2.z() / qmass)*part_prop,glu.x_t()+part_prop);
3962   q1.pos(position1); q2.pos(position2);
3963 
3964     qrks.add(q1); qrks.add(q2);
3965 }
3966 
3967 //finding a thermal sibling for a thermal parton in therm
3968 int HybridHadronization::findthermalsibling(int ithm, parton_collection& therm){
3969     if(!therm[therm[ithm].sibling()].is_used() && (therm[therm[ithm].sibling()].string_id() < 0) && (ithm != therm[ithm].sibling())){return therm[ithm].sibling();}
3970     int qrk_close = -1; double dist2min = 999999999999.;
3971     for(int i=0;i<therm.num();++i){
3972         if((therm[ithm].id() * therm[i].id() > 0) || therm[i].is_used()){continue;}
3973         double distnow = therm[ithm].posDif2(therm[i]) + (therm[ithm].x_t()-therm[i].x_t())*(therm[ithm].x_t()-therm[i].x_t());
3974         if(distnow < dist2min){qrk_close = i; dist2min = distnow;}
3975     }
3976     if(qrk_close == -1){qrk_close = ithm;}
3977     return qrk_close;
3978 }
3979 
3980 int HybridHadronization::findcloserepl(HHparton ptn, int iptn, bool lbt, bool thm, parton_collection& sh_lbt, parton_collection& therm){
3981 
3982     //should not happen
3983     if(iptn == 0 || ptn.id() == 21){throw std::runtime_error ("Parton index is incorrect (should not be 0 or gluon)");}
3984 
3985     //if the parton is thermal, and we're only looking at thermal partons, and the sibling was already found & not used, then return that.
3986     if((iptn<0) && thm && !lbt && !therm[ptn.sibling()].is_used() &&
3987       (((therm[ptn.sibling()].id() > 0) && (therm[ptn.sibling()].col() != 0)) || ((therm[ptn.sibling()].id() < 0) && (therm[ptn.sibling()].acol() != 0))) &&
3988       (iptn+1 != ptn.sibling())){return ptn.sibling();}
3989 
3990     //initializing vars
3991     int qrk_close = 999999999; double dist2min = 999999999999.;
3992     //checking thermal partons for closest parton
3993     if(thm){for(int i=0;i<therm.num();++i){
3994         //if the parton's color tag is not 0, then skip (is already repairing a string)
3995         if(((therm[i].id() > 0) && (therm[i].col() != 0)) || ((therm[i].id() < 0) && (therm[i].acol() != 0))){continue;}
3996         //if the parton is not a partner (eg. both quarks/antiquarks), or is used, or is the same as the input parton, skip it.
3997         if((ptn.id() * therm[i].id() > 0) || therm[i].is_used() || ((iptn<0) && (-i == iptn+1))){continue;}
3998         double distnow = ptn.posDif2(therm[i]) + (ptn.x_t()-therm[i].x_t())*(ptn.x_t()-therm[i].x_t());
3999         if(distnow < dist2min){qrk_close = -i-1; dist2min = distnow;}
4000     }}
4001     //checking lbt partons for closest parton
4002     if(lbt){for(int i=0;i<sh_lbt.num();++i){
4003         //if gluon, skip
4004         if(sh_lbt[i].id() == 21){continue;}
4005         //if the parton's color tag is not 0, then skip (not an lbt/martini? parton)
4006         if(((sh_lbt[i].id() > 0) && (sh_lbt[i].col() != 0)) || ((sh_lbt[i].id() < 0) && (sh_lbt[i].acol() != 0))){continue;}
4007         //if the parton is not a partner (eg. both quarks/antiquarks), or is used, or is the same as the input parton, skip it.
4008         if((ptn.id() * sh_lbt[i].id() > 0) || sh_lbt[i].is_used() || ((iptn>0) && (i == iptn-1))){continue;}
4009         double distnow = ptn.posDif2(sh_lbt[i]) + (ptn.x_t()-sh_lbt[i].x_t())*(ptn.x_t()-sh_lbt[i].x_t());
4010         if(distnow < dist2min){qrk_close = i+1; dist2min = distnow;}
4011     }}
4012 
4013     //positive return values indicate an lbt parton in the shower was found (the (i-1)th parton)
4014     //negative return values indicate a thermal parton was found (the -(i+1)th parton)
4015     return qrk_close;
4016 }
4017 
4018 //version to handle finding a q-qbar pair for lbt gluons
4019 void HybridHadronization::findcloserepl_glu(HHparton ptn, int iptn, bool lbt, bool thm, parton_collection& sh_lbt, parton_collection& therm, int sel_out[]){
4020 
4021     //should not happen
4022     if(iptn == 0 || ptn.id() != 21){throw std::runtime_error ("Parton index is incorrect (should not be 0, or anything other than gluon)");}
4023     if(ptn.is_thermal()){throw std::runtime_error ("Parton is thermal (should not be so)");}
4024 
4025     //initializing vars
4026     int qrk_close = 999999999; double dist2min = 999999999999.;
4027     //checking thermal partons for closest quark
4028     if(thm){for(int i=0;i<therm.num();++i){
4029         //if the parton's color tag is not 0, then skip (is already repairing a string), or skip if antiquark
4030         if(((therm[i].id() > 0) && (therm[i].col() != 0)) || (therm[i].id() < 0)){continue;}
4031         //if the parton is not a partner (eg. both quarks/antiquarks), or is used, or is the same as the input parton, skip it.
4032         if(therm[i].is_used() || ((iptn<0) && (-i == iptn+1))){continue;}
4033         double distnow = ptn.posDif2(therm[i]) + (ptn.x_t()-therm[i].x_t())*(ptn.x_t()-therm[i].x_t());
4034         if(distnow < dist2min){qrk_close = -i-1; dist2min = distnow;}
4035     }}
4036     //checking lbt partons for closest parton
4037     if(lbt){for(int i=0;i<sh_lbt.num();++i){
4038         //if gluon, skip
4039         if(sh_lbt[i].id() == 21){continue;}
4040         //if the parton's color tag is not 0, then skip (not an lbt/martini? parton), or skip if antiquark
4041         if(((sh_lbt[i].id() > 0) && (sh_lbt[i].col() != 0)) || (sh_lbt[i].id() < 0)){continue;}
4042         //if the parton is not a partner (eg. both quarks/antiquarks), or is used, or is the same as the input parton, skip it.
4043         if(sh_lbt[i].is_used() || ((iptn>0) && (i == iptn-1))){continue;}
4044         double distnow = ptn.posDif2(sh_lbt[i]) + (ptn.x_t()-sh_lbt[i].x_t())*(ptn.x_t()-sh_lbt[i].x_t());
4045         if(distnow < dist2min){qrk_close = i+1; dist2min = distnow;}
4046     }}
4047 
4048     //positive return values indicate an lbt parton in the shower was found (the (i-1)th parton)
4049     //negative return values indicate a thermal parton was found (the -(i+1)th parton)
4050     sel_out[0]=qrk_close;
4051 
4052     qrk_close = 999999999; dist2min = 999999999999.;
4053     //checking thermal partons for closest antiquark
4054     if(thm){for(int i=0;i<therm.num();++i){
4055         //if the parton's color tag is not 0, then skip (is already repairing a string), or skip if quark
4056         if((therm[i].id() > 0) || ((therm[i].id() < 0) && (therm[i].acol() != 0))){continue;}
4057         //if the parton is not a partner (eg. both quarks/antiquarks), or is used, or is the same as the input parton, skip it.
4058         if(therm[i].is_used() || ((iptn<0) && (-i == iptn+1))){continue;}
4059         double distnow = ptn.posDif2(therm[i]) + (ptn.x_t()-therm[i].x_t())*(ptn.x_t()-therm[i].x_t());
4060         if(distnow < dist2min){qrk_close = -i-1; dist2min = distnow;}
4061     }}
4062     //checking lbt partons for closest parton
4063     if(lbt){for(int i=0;i<sh_lbt.num();++i){
4064         //if gluon, skip
4065         if(sh_lbt[i].id() == 21){continue;}
4066         //if the parton's color tag is not 0, then skip (not an lbt/martini? parton), or skip if quark
4067         if((sh_lbt[i].id() > 0) || ((sh_lbt[i].id() < 0) && (sh_lbt[i].acol() != 0))){continue;}
4068         //if the parton is not a partner (eg. both quarks/antiquarks), or is used, or is the same as the input parton, skip it.
4069         if(sh_lbt[i].is_used() || ((iptn>0) && (i == iptn-1))){continue;}
4070         double distnow = ptn.posDif2(sh_lbt[i]) + (ptn.x_t()-sh_lbt[i].x_t())*(ptn.x_t()-sh_lbt[i].x_t());
4071         if(distnow < dist2min){qrk_close = i+1; dist2min = distnow;}
4072     }}
4073 
4074     //positive return values indicate an lbt parton in the shower was found (the (i-1)th parton)
4075     //negative return values indicate a thermal parton was found (the -(i+1)th parton)
4076     sel_out[1]=qrk_close;
4077 }
4078 
4079 //prepares remnant partons/strings for PYTHIA string hadronization
4080 //sorts strings, ensures strings are in 'valid' configurations, assigns color/anticolor tags
4081 //TODO: this might be where to use thermal partons to enforce color neutrality
4082 void HybridHadronization::stringprep(parton_collection& SP_remnants, parton_collection& SP_prepremn, bool cutstr){
4083   //dignostic measure
4084   /*std::cout <<endl<<"below is all the colors in the Tempjunction lists"<<endl;
4085   for(int ijunc=0; ijunc<Tempjunctions.size(); ijunc++){
4086     std::cout <<" { "<<Tempjunctions.at(ijunc).at(0).at(0)<<" , "<<Tempjunctions.at(ijunc).at(1).at(1)<<" , "<<Tempjunctions.at(ijunc).at(2).at(1)<<" , "<<Tempjunctions.at(ijunc).at(3).at(1)<<" } "<<endl;
4087     std::cout <<"col/acol: (" << Tempjunctions.at(ijunc).at(1).at(0) << "," << Tempjunctions.at(ijunc).at(2).at(0) << "," << Tempjunctions.at(ijunc).at(3).at(0) << ")" << std::endl;
4088   }*/
4089   //Declare essential vectors for string repair
4090   vector<vector<vector<HHparton>>> JuncStructure;
4091   vector<vector<HHparton>> JuncLegs; // vector of all junction ( Junction Num, Leg1, Leg2, Leg3)
4092   vector<HHparton> Leg1; // partons in the legs for juncion formation
4093   vector<HHparton> Leg2;
4094   vector<HHparton> Leg3;
4095   vector<int> Legconsidering;//address of partons in SP_remnants
4096   vector<vector<vector<int>>> IMStructure1; //Intermediate structure for saving the indices in Tempjunction and Corresponding Leg Number, this will be used for cutting string for appending info to PYTHIA
4097   vector<vector<int>> IMStructure2; // this will contain Tempjunction Indice and -+1 and leg numbers
4098   //ex. 2nd lef in 3rd temp anti junction is same as 1st leg 2nd tempjunction. 3,-1,0,0   3,1,2,0 would be saved in the vectorIMS1
4099   vector<int> IMStructure3; // 4 element vector of Tempjunction order, kind and leg address in JuncStructure vector
4100   vector<vector<HHparton>> Recombearly1; //these partons are in the junction with three or two shared legs with others , and they will be recombined into baryon to cut? or arrange the string for PYTHIA to understand input come from this code
4101   vector<HHparton> Recombearly2;
4102   vector<vector<vector<HHparton>>> Dijunction1; // these partons are in the junction with two legs shared legs!
4103   vector<vector<HHparton>> Dijunction2;
4104   //Vector of Indices for Dijunction1 vector to be ordered for invoking Pythia
4105   vector<vector<int>> DijunctionInfo1;
4106   vector<int> DijunctionInfo2; //  { -1: antiJ, +1 : J , 0 : shared leg}
4107   //these tags should be assigned to corresponding legs in Dijunction1 vector! so DijunctionInfo2 has five elements{since, dijunction structure has five legs!}
4108 
4109 
4110   vector<vector<vector<HHparton>>> Singlejunction1; // easiest case! just single string
4111   vector<vector<HHparton>> Singlejunction2;
4112   vector<vector<HHparton>> Tailoredstring1; // when there are the junction with two shared legs, it also should be recombined into baryon and one string will remain after, which would be saved in this vector
4113   vector<HHparton> Tailoredstring2;
4114   vector<int> realjuncindice; // vector to save the indice of Tempjunction when real junction is formed by three initiating particle
4115 
4116   vector<HHparton> finalstring; // final space for all of the remnant particles being corrected by fake parton addition
4117 
4118   /*JSINFO << "SP_remnants before stringprep:";
4119   for(int irem=0; irem < SP_remnants.num(); ++irem) {
4120     std::cout << SP_remnants[irem].id() << "," << SP_remnants[irem].col() << "," << SP_remnants[irem].acol() << std::endl;
4121   }*/
4122 
4123   // Tempjunctions missing partons? Add thermal or fake
4124   // find the maximum (anti-)color tag in the remnants list and the tempjunctions
4125   int maxtag = 0;
4126   for(int irem=0; irem < SP_remnants.num(); ++irem) {
4127     if(SP_remnants[irem].col() > maxtag) {
4128       maxtag = SP_remnants[irem].col();
4129     }
4130     if(SP_remnants[irem].acol() > maxtag) {
4131       maxtag = SP_remnants[irem].acol();
4132     }
4133   }
4134   for(int ijunc=0; ijunc < Tempjunctions.size(); ++ijunc) {
4135     if(Tempjunctions.at(ijunc).at(1).at(1) > maxtag) {
4136       maxtag = Tempjunctions.at(ijunc).at(1).at(1);
4137     }
4138     if(Tempjunctions.at(ijunc).at(2).at(1) > maxtag) {
4139       maxtag = Tempjunctions.at(ijunc).at(2).at(1);
4140     }
4141     if(Tempjunctions.at(ijunc).at(3).at(1) > maxtag) {
4142       maxtag = Tempjunctions.at(ijunc).at(3).at(1);
4143     }
4144   }
4145 
4146   HHparton tempparton1;
4147   HHparton tempparton2;
4148   HHparton tempparton3;
4149   for(int ijunc=0; ijunc < Tempjunctions.size(); ++ijunc) {
4150     int i1 = 0; int i2 = 0; int i3 = 0;
4151 
4152     // First try to match to remant parton color/anticolor tags and write matching parton index into tag
4153     for(int irem=0; irem < SP_remnants.num(); ++irem) {
4154       if(Tempjunctions.at(ijunc).at(0).at(0) == -1) {
4155         if(SP_remnants[irem].acol() == Tempjunctions.at(ijunc).at(1).at(1) && Tempjunctions.at(ijunc).at(1).at(1) != 0) {i1 = irem+1;}
4156         if(SP_remnants[irem].acol() == Tempjunctions.at(ijunc).at(2).at(1) && Tempjunctions.at(ijunc).at(2).at(1) != 0) {i2 = irem+1;}
4157         if(SP_remnants[irem].acol() == Tempjunctions.at(ijunc).at(3).at(1) && Tempjunctions.at(ijunc).at(3).at(1) != 0) {i3 = irem+1;}
4158       }else if(Tempjunctions.at(ijunc).at(0).at(0) == 1) {
4159         if(SP_remnants[irem].col() == Tempjunctions.at(ijunc).at(1).at(1) && Tempjunctions.at(ijunc).at(1).at(1) != 0) {i1 = irem+1;}
4160         if(SP_remnants[irem].col() == Tempjunctions.at(ijunc).at(2).at(1) && Tempjunctions.at(ijunc).at(2).at(1) != 0) {i2 = irem+1;}
4161         if(SP_remnants[irem].col() == Tempjunctions.at(ijunc).at(3).at(1) && Tempjunctions.at(ijunc).at(3).at(1) != 0) {i3 = irem+1;}
4162       }
4163     }
4164 
4165     // Now try to find partners in another temp junction, store junction and leg number as a negative tag
4166     for(int ijunc2=ijunc+1; ijunc2 < Tempjunctions.size(); ++ijunc2) {
4167       if((Tempjunctions.at(ijunc).at(0).at(0) == -1 && Tempjunctions.at(ijunc2).at(0).at(0) == 1) || (Tempjunctions.at(ijunc).at(0).at(0) == 1 && Tempjunctions.at(ijunc2).at(0).at(0) == -1)) {
4168         for(int ileg=1; ileg <= 3; ++ileg) {
4169           if(Tempjunctions.at(ijunc2).at(ileg).at(1) == Tempjunctions.at(ijunc).at(1).at(1) && Tempjunctions.at(ijunc).at(1).at(1) != 0) {i1 = -ijunc2*10-ileg;}
4170           if(Tempjunctions.at(ijunc2).at(ileg).at(1) == Tempjunctions.at(ijunc).at(2).at(1) && Tempjunctions.at(ijunc).at(2).at(1) != 0) {i2 = -ijunc2*10-ileg;}
4171           if(Tempjunctions.at(ijunc2).at(ileg).at(1) == Tempjunctions.at(ijunc).at(3).at(1) && Tempjunctions.at(ijunc).at(3).at(1) != 0) {i3 = -ijunc2*10-ileg;}
4172         }
4173       }else{
4174         bool warning = false;
4175         for (int ileg=1; ileg <= 3; ++ileg) {
4176           for (int jleg=1; jleg <= 3; ++jleg) {
4177             if (Tempjunctions.at(ijunc).at(ileg).at(1) == Tempjunctions.at(ijunc2).at(jleg).at(1)) {
4178               warning = true;
4179             }
4180           }
4181         }
4182         if(warning) {
4183           JSWARN << "There is a junction pair which is not junction-antijunction, but junction-junction or antijunction-antijunction. This should not happen!";
4184         }
4185       }
4186     }
4187 
4188     // define temporary parton to be used in findclosereplica
4189     if(i1 <= 0) {
4190       if(i2 > 0){
4191         tempparton1 = SP_remnants[i2-1];
4192         if(std::abs(tempparton1.id()) < 6){ // no change of colors here, they are not important in findclosereplica
4193           tempparton1.id(-tempparton1.id());
4194         }
4195       }else if(i3 > 0){
4196         tempparton1 = SP_remnants[i3-1];
4197         if(std::abs(tempparton1.id()) < 6){
4198           tempparton1.id(-tempparton1.id());
4199         }
4200       }else{ // should be very rare: junction with 3 ghost legs
4201         tempparton1 = SP_remnants[0];
4202         if(Tempjunctions.at(ijunc).at(0).at(0) == -1 && std::abs(tempparton1.id()) < 6 && tempparton1.id() < 0){
4203           tempparton1.id(-tempparton1.id());
4204         } else if(Tempjunctions.at(ijunc).at(0).at(0) == 1 && std::abs(tempparton1.id()) < 6 && tempparton1.id() > 0){
4205           tempparton1.id(-tempparton1.id());
4206         }
4207       }
4208     }
4209     if(i2 <= 0) {
4210       if(i1 > 0){
4211         tempparton2 = SP_remnants[i1-1];
4212         if(std::abs(tempparton2.id()) < 6){ // no change of colors here, they are not important in findclosereplica
4213           tempparton2.id(-tempparton2.id());
4214         }
4215       }else if(i3 > 0){
4216         tempparton2 = SP_remnants[i3-1];
4217         if(std::abs(tempparton2.id()) < 6){
4218           tempparton2.id(-tempparton2.id());
4219         }
4220       }else{ // should be very rare: junction with 3 ghost legs
4221         tempparton2 = SP_remnants[0];
4222         if(Tempjunctions.at(ijunc).at(0).at(0) == -1 && std::abs(tempparton2.id()) < 6 && tempparton2.id() < 0){
4223           tempparton2.id(-tempparton2.id());
4224         } else if(Tempjunctions.at(ijunc).at(0).at(0) == 1 && std::abs(tempparton2.id()) < 6 && tempparton2.id() > 0){
4225           tempparton2.id(-tempparton2.id());
4226         }
4227       }
4228     }
4229     if(i3 <= 0) {
4230       if(i1 > 0){
4231         tempparton3 = SP_remnants[i1-1];
4232         if(std::abs(tempparton3.id()) < 6){ // no change of colors here, they are not important in findclosereplica
4233           tempparton3.id(-tempparton3.id());
4234         }
4235       }else if(i2 > 0){
4236         tempparton3 = SP_remnants[i2-1];
4237         if(std::abs(tempparton3.id()) < 6){
4238           tempparton3.id(-tempparton3.id());
4239         }
4240       }else{ // should be very rare: junction with 3 ghost legs
4241         tempparton3 = SP_remnants[0];
4242         if(Tempjunctions.at(ijunc).at(0).at(0) == -1 && std::abs(tempparton3.id()) < 6 && tempparton3.id() < 0){
4243           tempparton3.id(-tempparton3.id());
4244         } else if(Tempjunctions.at(ijunc).at(0).at(0) == 1 && std::abs(tempparton3.id()) < 6 && tempparton3.id() > 0){
4245           tempparton3.id(-tempparton3.id());
4246         }
4247       }
4248     }
4249 
4250     if(i1 == 0 || i2 == 0 || i3 == 0){
4251       Tempjunctions.at(ijunc).at(0).at(1) = 1; // at least one thermal parton in (anti-)junction
4252     }
4253 
4254     // Now find partons to add to missing junction legs; either thermal or fake
4255     if(i1 == 0 && Tempjunctions.at(ijunc).at(0).at(0) == -1) {
4256       int loc = 0;
4257       if(tempparton1.id() == 21) {
4258         tempparton1.id(1);
4259         loc = findcloserepl(tempparton1,1, false, true, HH_showerptns, HH_thermal);
4260         tempparton1.id(21);
4261       }else{loc = findcloserepl(tempparton1,1, false, true, HH_showerptns, HH_thermal);}
4262       if(loc == 999999999 || loc > 0) {
4263         int fid = ((ran() > 0.33333333) ? ((ran() > 0.5) ? -1 : -2) : -3);
4264         HHparton fakep = tempparton1; fakep.id(fid); fakep.set_color(0);
4265         if(Tempjunctions.at(ijunc).at(1).at(1) != 0) {
4266           fakep.set_anti_color(Tempjunctions.at(ijunc).at(1).at(1));
4267         } else {
4268           fakep.set_anti_color(++maxtag);
4269           Tempjunctions.at(ijunc).at(1).at(1) = maxtag;
4270         }
4271         if(std::abs(fakep.id()) < 3) {
4272           fakep.mass(xmq);
4273         } else {fakep.mass(xms);}
4274         double fake_pT = (p_fake >= 1.) ? 0.282842712474619 : 0.; double fake_phi = 2. * 3.14159265358979 * ran();
4275         fakep.px(fake_pT * cos(fake_phi)); fakep.py(fake_pT * sin(fake_phi));
4276         if (number_p_fake == 0 || number_p_fake == 2){
4277           fakep.pz(-p_fake);
4278         } else if (number_p_fake == 1 || number_p_fake == 3) {
4279           fakep.pz(p_fake);
4280         } else {fakep.pz(0.);}
4281         number_p_fake++;
4282         fakep.e(std::sqrt(fakep.px()*fakep.px() + fakep.py()*fakep.py() + fakep.pz()*fakep.pz() + fakep.mass()*fakep.mass()));
4283         fakep.orig(-1); fakep.is_remnant(true);
4284         fakep.is_fakeparton(true);
4285         SP_remnants.add(fakep);
4286       }else if(loc < 0) {
4287         if(Tempjunctions.at(ijunc).at(1).at(1) != 0) {
4288           HH_thermal[-loc-1].acol(Tempjunctions.at(ijunc).at(1).at(1));
4289         } else {
4290           HH_thermal[-loc-1].acol(++maxtag);
4291           Tempjunctions.at(ijunc).at(1).at(1) = maxtag;
4292         }
4293         HH_thermal[-loc-1].col(0);
4294         HH_thermal[-loc-1].is_used(true);
4295         HH_thermal[-loc-1].is_remnant(true);
4296         SP_remnants.add(HH_thermal[-loc-1]);
4297         SP_remnants[SP_remnants.num()-1].par(-loc-1);
4298       }
4299     }
4300 
4301     if(i2 == 0 && Tempjunctions.at(ijunc).at(0).at(0) == -1 ) {
4302       int loc = 0;
4303       if(tempparton2.id() == 21) {
4304         tempparton2.id(1);
4305         loc = findcloserepl(tempparton2,1, false, true, HH_showerptns, HH_thermal);
4306         tempparton2.id(21);
4307       }else{loc = findcloserepl(tempparton2,1, false, true, HH_showerptns, HH_thermal);}
4308       if(loc == 999999999 || loc > 0) {
4309           int fid = ((ran() > 0.33333333) ? ((ran() > 0.5) ? -1 : -2) : -3);
4310         HHparton fakep = tempparton2; fakep.id(fid); fakep.set_color(0);
4311         if(Tempjunctions.at(ijunc).at(2).at(1) != 0) {
4312           fakep.set_anti_color(Tempjunctions.at(ijunc).at(2).at(1));
4313         } else {
4314           fakep.set_anti_color(++maxtag);
4315           Tempjunctions.at(ijunc).at(2).at(1) = maxtag;
4316         }
4317         if(std::abs(fakep.id()) < 3) {
4318           fakep.mass(xmq);
4319         } else {fakep.mass(xms);}
4320         double fake_pT = (p_fake >= 1.) ? 0.282842712474619 : 0.; double fake_phi = 2. * 3.14159265358979 * ran();
4321         fakep.px(fake_pT * cos(fake_phi)); fakep.py(fake_pT * sin(fake_phi));
4322         if (number_p_fake == 0 || number_p_fake == 2){
4323           fakep.pz(-p_fake);
4324         } else if (number_p_fake == 1 || number_p_fake == 3) {
4325           fakep.pz(p_fake);
4326         } else {fakep.pz(0.);}
4327         number_p_fake++;
4328         fakep.e(std::sqrt(fakep.px()*fakep.px() + fakep.py()*fakep.py() + fakep.pz()*fakep.pz() + fakep.mass()*fakep.mass()));
4329         fakep.orig(-1); fakep.is_remnant(true);
4330         fakep.is_fakeparton(true);
4331         SP_remnants.add(fakep);
4332       }else if(loc < 0) {
4333         if(Tempjunctions.at(ijunc).at(2).at(1) != 0) {
4334           HH_thermal[-loc-1].acol(Tempjunctions.at(ijunc).at(2).at(1));
4335         } else {
4336           HH_thermal[-loc-1].acol(++maxtag);
4337           Tempjunctions.at(ijunc).at(2).at(1) = maxtag;
4338         }
4339         HH_thermal[-loc-1].col(0);
4340         HH_thermal[-loc-1].is_used(true);
4341         HH_thermal[-loc-1].is_remnant(true);
4342         SP_remnants.add(HH_thermal[-loc-1]);
4343         SP_remnants[SP_remnants.num()-1].par(-loc-1);
4344       }
4345     }
4346 
4347     if(i3 == 0 && Tempjunctions.at(ijunc).at(0).at(0) == -1) {
4348       int loc = 0;
4349       if(tempparton3.id() == 21) {
4350         tempparton3.id(1);
4351         loc = findcloserepl(tempparton3,1, false, true, HH_showerptns, HH_thermal);
4352         tempparton3.id(21);
4353       }else{loc = findcloserepl(tempparton3,1, false, true, HH_showerptns, HH_thermal);}
4354       if(loc == 999999999 || loc > 0) {
4355           int fid = ((ran() > 0.33333333) ? ((ran() > 0.5) ? -1 : -2) : -3);
4356         HHparton fakep = tempparton3; fakep.id(fid); fakep.set_color(0);
4357         if(Tempjunctions.at(ijunc).at(3).at(1) != 0) {
4358           fakep.set_anti_color(Tempjunctions.at(ijunc).at(3).at(1));
4359         } else {
4360           fakep.set_anti_color(++maxtag);
4361           Tempjunctions.at(ijunc).at(3).at(1) = maxtag;
4362         }
4363         if(std::abs(fakep.id()) < 3) {
4364           fakep.mass(xmq);
4365         } else {fakep.mass(xms);}
4366         double fake_pT = (p_fake >= 1.) ? 0.282842712474619 : 0.; double fake_phi = 2. * 3.14159265358979 * ran();
4367         fakep.px(fake_pT * cos(fake_phi)); fakep.py(fake_pT * sin(fake_phi));
4368         if (number_p_fake == 0 || number_p_fake == 2){
4369           fakep.pz(-p_fake);
4370         } else if (number_p_fake == 1 || number_p_fake == 3) {
4371           fakep.pz(p_fake);
4372         } else {fakep.pz(0.);}
4373         number_p_fake++;
4374         fakep.e(std::sqrt(fakep.px()*fakep.px() + fakep.py()*fakep.py() + fakep.pz()*fakep.pz() + fakep.mass()*fakep.mass()));
4375         fakep.orig(-1); fakep.is_remnant(true);
4376         fakep.is_fakeparton(true);
4377         SP_remnants.add(fakep);
4378       }else if(loc < 0) {
4379         if(Tempjunctions.at(ijunc).at(3).at(1) != 0) {
4380           HH_thermal[-loc-1].acol(Tempjunctions.at(ijunc).at(3).at(1));
4381         } else {
4382           HH_thermal[-loc-1].acol(++maxtag);
4383           Tempjunctions.at(ijunc).at(3).at(1) = maxtag;
4384         }
4385         HH_thermal[-loc-1].col(0);
4386         HH_thermal[-loc-1].is_used(true);
4387         HH_thermal[-loc-1].is_remnant(true);
4388         SP_remnants.add(HH_thermal[-loc-1]);
4389         SP_remnants[SP_remnants.num()-1].par(-loc-1);
4390       }
4391     }
4392 
4393     if(i1 == 0 && Tempjunctions.at(ijunc).at(0).at(0) == 1) {
4394       int loc = 0;
4395       if(tempparton1.id() == 21) {
4396         tempparton1.id(-1);
4397         loc = findcloserepl(tempparton1,1, false, true, HH_showerptns, HH_thermal);
4398         tempparton1.id(21);
4399       }else{loc = findcloserepl(tempparton1,1, false, true, HH_showerptns, HH_thermal);}
4400       if(loc == 999999999 || loc > 0) {
4401           int fid = ((ran() > 0.33333333) ? ((ran() > 0.5) ? 1 : 2) : 3);
4402         HHparton fakep = tempparton1; fakep.id(fid);
4403         fakep.set_anti_color(0);
4404         if(Tempjunctions.at(ijunc).at(1).at(1) != 0) {
4405           fakep.set_color(Tempjunctions.at(ijunc).at(1).at(1));
4406         } else {
4407           fakep.set_color(++maxtag);
4408           Tempjunctions.at(ijunc).at(1).at(1) = maxtag;
4409         }
4410         if(std::abs(fakep.id()) < 3) {
4411           fakep.mass(xmq);
4412         } else {fakep.mass(xms);}
4413         double fake_pT = (p_fake >= 1.) ? 0.282842712474619 : 0.; double fake_phi = 2. * 3.14159265358979 * ran();
4414         fakep.px(fake_pT * cos(fake_phi)); fakep.py(fake_pT * sin(fake_phi));
4415         if (number_p_fake == 0 || number_p_fake == 2){
4416           fakep.pz(-p_fake);
4417         } else if (number_p_fake == 1 || number_p_fake == 3) {
4418           fakep.pz(p_fake);
4419         } else {fakep.pz(0.);}
4420         number_p_fake++;
4421         fakep.e(std::sqrt(fakep.px()*fakep.px() + fakep.py()*fakep.py() + fakep.pz()*fakep.pz() + fakep.mass()*fakep.mass()));
4422         fakep.orig(-1); fakep.is_remnant(true);
4423         fakep.is_fakeparton(true);
4424         SP_remnants.add(fakep);
4425       }else if(loc < 0) {
4426         if(Tempjunctions.at(ijunc).at(1).at(1) != 0) {
4427           HH_thermal[-loc-1].col(Tempjunctions.at(ijunc).at(1).at(1));
4428         } else {
4429           HH_thermal[-loc-1].col(++maxtag);
4430           Tempjunctions.at(ijunc).at(1).at(1) = maxtag;
4431         }
4432         HH_thermal[-loc-1].acol(0);
4433         HH_thermal[-loc-1].is_used(true);
4434         HH_thermal[-loc-1].is_remnant(true);
4435         SP_remnants.add(HH_thermal[-loc-1]);
4436         SP_remnants[SP_remnants.num()-1].par(-loc-1);
4437       }
4438     }
4439 
4440     if(i2 == 0 && Tempjunctions.at(ijunc).at(0).at(0) == 1) {
4441       int loc = 0;
4442       if(tempparton2.id() == 21) {
4443         tempparton2.id(-1);
4444         loc = findcloserepl(tempparton2,1, false, true, HH_showerptns, HH_thermal);
4445         tempparton2.id(21);
4446       }else{loc = findcloserepl(tempparton2,1, false, true, HH_showerptns, HH_thermal);}
4447       if(loc == 999999999 || loc > 0) {
4448           int fid = ((ran() > 0.33333333) ? ((ran() > 0.5) ? 1 : 2) : 3);
4449         HHparton fakep = tempparton2; fakep.id(fid);
4450         fakep.set_anti_color(0);
4451         if(Tempjunctions.at(ijunc).at(2).at(1) != 0) {
4452           fakep.set_color(Tempjunctions.at(ijunc).at(2).at(1));
4453         } else {
4454           fakep.set_color(++maxtag);
4455           Tempjunctions.at(ijunc).at(2).at(1) = maxtag;
4456         }
4457         if(std::abs(fakep.id()) < 3) {
4458           fakep.mass(xmq);
4459         } else {fakep.mass(xms);}
4460         double fake_pT = (p_fake >= 1.) ? 0.282842712474619 : 0.; double fake_phi = 2. * 3.14159265358979 * ran();
4461         fakep.px(fake_pT * cos(fake_phi)); fakep.py(fake_pT * sin(fake_phi));
4462         if (number_p_fake == 0 || number_p_fake == 2){
4463           fakep.pz(-p_fake);
4464         } else if (number_p_fake == 1 || number_p_fake == 3) {
4465           fakep.pz(p_fake);
4466         } else {fakep.pz(0.);}
4467         number_p_fake++;
4468         fakep.e(std::sqrt(fakep.px()*fakep.px() + fakep.py()*fakep.py() + fakep.pz()*fakep.pz() + fakep.mass()*fakep.mass()));
4469         fakep.orig(-1); fakep.is_remnant(true);
4470         fakep.is_fakeparton(true);
4471         SP_remnants.add(fakep);
4472       }else if(loc < 0) {
4473         if(Tempjunctions.at(ijunc).at(2).at(1) != 0) {
4474           HH_thermal[-loc-1].col(Tempjunctions.at(ijunc).at(2).at(1));
4475         } else {
4476           HH_thermal[-loc-1].col(++maxtag);
4477           Tempjunctions.at(ijunc).at(2).at(1) = maxtag;
4478         }
4479         HH_thermal[-loc-1].acol(0);
4480         HH_thermal[-loc-1].is_used(true);
4481         HH_thermal[-loc-1].is_remnant(true);
4482         SP_remnants.add(HH_thermal[-loc-1]);
4483         SP_remnants[SP_remnants.num()-1].par(-loc-1);
4484       }
4485     }
4486 
4487     if(i3 == 0 && Tempjunctions.at(ijunc).at(0).at(0) == 1) {
4488       int loc = 0;
4489       if(tempparton3.id() == 21) {
4490         tempparton3.id(-1);
4491         loc = findcloserepl(tempparton3,1, false, true, HH_showerptns, HH_thermal);
4492         tempparton3.id(21);
4493       }else{loc = findcloserepl(tempparton3,1, false, true, HH_showerptns, HH_thermal);}
4494       if(loc == 999999999 || loc > 0) {
4495           int fid = ((ran() > 0.33333333) ? ((ran() > 0.5) ? 1 : 2) : 3);
4496         HHparton fakep = tempparton3; fakep.id(fid);
4497         fakep.set_anti_color(0);
4498         if(Tempjunctions.at(ijunc).at(3).at(1) != 0) {
4499           fakep.set_color(Tempjunctions.at(ijunc).at(3).at(1));
4500         } else {
4501           fakep.set_color(++maxtag);
4502           Tempjunctions.at(ijunc).at(3).at(1) = maxtag;
4503         }
4504         if(std::abs(fakep.id()) < 3) {
4505           fakep.mass(xmq);
4506         } else {fakep.mass(xms);}
4507         double fake_pT = (p_fake >= 1.) ? 0.282842712474619 : 0.; double fake_phi = 2. * 3.14159265358979 * ran();
4508         fakep.px(fake_pT * cos(fake_phi)); fakep.py(fake_pT * sin(fake_phi));
4509         if (number_p_fake == 0 || number_p_fake == 2){
4510           fakep.pz(-p_fake);
4511         } else if (number_p_fake == 1 || number_p_fake == 3) {
4512           fakep.pz(p_fake);
4513         } else {fakep.pz(0.);}
4514         number_p_fake++;
4515         fakep.e(std::sqrt(fakep.px()*fakep.px() + fakep.py()*fakep.py() + fakep.pz()*fakep.pz() + fakep.mass()*fakep.mass()));
4516         fakep.orig(-1); fakep.is_remnant(true);
4517         fakep.is_fakeparton(true);
4518         SP_remnants.add(fakep);
4519       }else if(loc < 0) {
4520         if(Tempjunctions.at(ijunc).at(3).at(1) != 0) {
4521           HH_thermal[-loc-1].col(Tempjunctions.at(ijunc).at(3).at(1));
4522         } else {
4523           HH_thermal[-loc-1].col(++maxtag);
4524           Tempjunctions.at(ijunc).at(3).at(1) = maxtag;
4525         }
4526         HH_thermal[-loc-1].acol(0);
4527         HH_thermal[-loc-1].is_used(true);
4528         HH_thermal[-loc-1].is_remnant(true);
4529         SP_remnants.add(HH_thermal[-loc-1]);
4530         SP_remnants[SP_remnants.num()-1].par(-loc-1);
4531       }
4532     }
4533 
4534     // Add fake gluons (no beam energies) between junctions with empty connecting legs [handling could be improved later]
4535     if(i1 < 0 && Tempjunctions.at(ijunc).at(0).at(0) == -1 ) {
4536       int jleg = ((-i1) % 10);
4537       int jjunc = ((-i1)-jleg)/10;
4538       HHparton fakep = tempparton1; fakep.id(21);
4539       fakep.set_color(++maxtag);
4540       fakep.set_anti_color(Tempjunctions.at(ijunc).at(1).at(1));
4541       fakep.mass(1e-2); // 10 MeV "accuracy"
4542       Tempjunctions.at(jjunc).at(jleg).at(1) = maxtag;
4543       double fake_pT = (p_fake >= 1.) ? 0.282842712474619 : 0.; double fake_phi = 2. * 3.14159265358979 * ran();
4544       fakep.px(fake_pT * cos(fake_phi)); fakep.py(fake_pT * sin(fake_phi)); fakep.pz(0.);
4545       fakep.e(std::sqrt(fakep.px()*fakep.px() + fakep.py()*fakep.py() + fakep.pz()*fakep.pz() + fakep.mass()*fakep.mass()));
4546       fakep.orig(-1); fakep.is_remnant(true);
4547       fakep.is_fakeparton(true);
4548       SP_remnants.add(fakep);
4549     }
4550 
4551     if(i2 < 0 && Tempjunctions.at(ijunc).at(0).at(0) == -1 ) {
4552       int jleg = ((-i2) % 10);
4553       int jjunc = ((-i2)-jleg)/10;
4554       HHparton fakep = tempparton2; fakep.id(21);
4555       fakep.set_color(++maxtag);
4556       fakep.set_anti_color(Tempjunctions.at(ijunc).at(2).at(1));
4557       fakep.mass(1e-2);
4558       Tempjunctions.at(jjunc).at(jleg).at(1) = maxtag;
4559       double fake_pT = (p_fake >= 1.) ? 0.282842712474619 : 0.; double fake_phi = 2. * 3.14159265358979 * ran();
4560       fakep.px(fake_pT * cos(fake_phi)); fakep.py(fake_pT * sin(fake_phi)); fakep.pz(0.);
4561       fakep.e(std::sqrt(fakep.px()*fakep.px() + fakep.py()*fakep.py() + fakep.pz()*fakep.pz() + fakep.mass()*fakep.mass()));
4562       fakep.orig(-1); fakep.is_remnant(true);
4563       fakep.is_fakeparton(true);
4564       SP_remnants.add(fakep);
4565     }
4566 
4567     if(i3 < 0 && Tempjunctions.at(ijunc).at(0).at(0) == -1 ) {
4568       int jleg = ((-i3) % 10);
4569       int jjunc = ((-i3)-jleg)/10;
4570       HHparton fakep = tempparton3; fakep.id(21);
4571       fakep.set_color(++maxtag);
4572       fakep.set_anti_color(Tempjunctions.at(ijunc).at(3).at(1));
4573       fakep.mass(1e-2);
4574       Tempjunctions.at(jjunc).at(jleg).at(1) = maxtag;
4575       double fake_pT = (p_fake >= 1.) ? 0.282842712474619 : 0.; double fake_phi = 2. * 3.14159265358979 * ran();
4576       fakep.px(fake_pT * cos(fake_phi)); fakep.py(fake_pT * sin(fake_phi)); fakep.pz(0.);
4577       fakep.e(std::sqrt(fakep.px()*fakep.px() + fakep.py()*fakep.py() + fakep.pz()*fakep.pz() + fakep.mass()*fakep.mass()));
4578       fakep.orig(-1); fakep.is_remnant(true);
4579       fakep.is_fakeparton(true);
4580       SP_remnants.add(fakep);
4581     }
4582 
4583     if(i1 < 0 && Tempjunctions.at(ijunc).at(0).at(0) == 1 ) {
4584       int jleg = ((-i1) % 10);
4585       int jjunc = ((-i1)-jleg)/10;
4586       HHparton fakep = tempparton1; fakep.id(21);
4587       fakep.set_anti_color(++maxtag);
4588       fakep.set_color(Tempjunctions.at(ijunc).at(1).at(1));
4589       fakep.mass(1e-2);
4590       Tempjunctions.at(jjunc).at(jleg).at(1) = maxtag;
4591       double fake_pT = (p_fake >= 1.) ? 0.282842712474619 : 0.; double fake_phi = 2. * 3.14159265358979 * ran();
4592       fakep.px(fake_pT * cos(fake_phi)); fakep.py(fake_pT * sin(fake_phi)); fakep.pz(0.);
4593       fakep.e(std::sqrt(fakep.px()*fakep.px() + fakep.py()*fakep.py() + fakep.pz()*fakep.pz() + fakep.mass()*fakep.mass()));
4594       fakep.orig(-1); fakep.is_remnant(true);
4595       fakep.is_fakeparton(true);
4596       SP_remnants.add(fakep);
4597     }
4598 
4599     if(i2 < 0 && Tempjunctions.at(ijunc).at(0).at(0) == 1 ) {
4600       int jleg = ((-i2) % 10);
4601       int jjunc = ((-i2)-jleg)/10;
4602       HHparton fakep = tempparton2; fakep.id(21);
4603       fakep.set_anti_color(++maxtag);
4604       fakep.set_color(Tempjunctions.at(ijunc).at(2).at(1));
4605       fakep.mass(1e-2);
4606       Tempjunctions.at(jjunc).at(jleg).at(1) = maxtag;
4607       double fake_pT = (p_fake >= 1.) ? 0.282842712474619 : 0.; double fake_phi = 2. * 3.14159265358979 * ran();
4608       fakep.px(fake_pT * cos(fake_phi)); fakep.py(fake_pT * sin(fake_phi)); fakep.pz(0.);
4609       fakep.e(std::sqrt(fakep.px()*fakep.px() + fakep.py()*fakep.py() + fakep.pz()*fakep.pz() + fakep.mass()*fakep.mass()));
4610       fakep.orig(-1); fakep.is_remnant(true);
4611       fakep.is_fakeparton(true);
4612       SP_remnants.add(fakep);
4613     }
4614 
4615     if(i3 < 0 && Tempjunctions.at(ijunc).at(0).at(0) == 1 ) {
4616       int jleg = ((-i3) % 10);
4617       int jjunc = ((-i3)-jleg)/10;
4618       HHparton fakep = tempparton3; fakep.id(21);
4619       fakep.set_anti_color(++maxtag);
4620       fakep.set_color(Tempjunctions.at(ijunc).at(3).at(1));
4621       fakep.mass(1e-2);
4622       Tempjunctions.at(jjunc).at(jleg).at(1) = maxtag;
4623       double fake_pT = (p_fake >= 1.) ? 0.282842712474619 : 0.; double fake_phi = 2. * 3.14159265358979 * ran();
4624       fakep.px(fake_pT * cos(fake_phi)); fakep.py(fake_pT * sin(fake_phi)); fakep.pz(0.);
4625       fakep.e(std::sqrt(fakep.px()*fakep.px() + fakep.py()*fakep.py() + fakep.pz()*fakep.pz() + fakep.mass()*fakep.mass()));
4626       fakep.orig(-1); fakep.is_remnant(true);
4627       fakep.is_fakeparton(true);
4628       SP_remnants.add(fakep);
4629     }
4630   }
4631 
4632   // repair all strings (add missing partons)
4633   for(int ptn1 = 0; ptn1 < SP_remnants.num(); ptn1++) {
4634     bool colors_match = false;
4635     bool anti_colors_match = false;
4636     int ptn1_col = SP_remnants[ptn1].col();
4637     int ptn1_acol = SP_remnants[ptn1].acol();
4638     for(int ptn2 = 0; ptn2 < SP_remnants.num(); ptn2++) {
4639       int ptn2_acol = SP_remnants[ptn2].acol();
4640       int ptn2_col = SP_remnants[ptn2].col();
4641       if(ptn1_col == ptn2_acol) {colors_match = true;}
4642       if(ptn1_acol == ptn2_col) {anti_colors_match = true;}
4643     }
4644     if(!colors_match || !anti_colors_match) {
4645       for(int ijunc = 0; ijunc < Tempjunctions.size(); ijunc++) {
4646         if(Tempjunctions.at(ijunc).at(0).at(0) == 1 && (ptn1_col == Tempjunctions.at(ijunc).at(1).at(1) || ptn1_col == Tempjunctions.at(ijunc).at(2).at(1) || ptn1_col == Tempjunctions.at(ijunc).at(3).at(1))) {
4647           colors_match = true;
4648         }
4649         if(Tempjunctions.at(ijunc).at(0).at(0) == -1 && (ptn1_acol == Tempjunctions.at(ijunc).at(1).at(1) || ptn1_acol == Tempjunctions.at(ijunc).at(2).at(1) || ptn1_acol == Tempjunctions.at(ijunc).at(3).at(1))) {
4650           anti_colors_match = true;
4651         }
4652       }
4653     }
4654     if(!colors_match && SP_remnants[ptn1].id() > 0) {
4655       int loc = 0;
4656       if(SP_remnants[ptn1].id() == 21){
4657         SP_remnants[ptn1].id(1);
4658         loc = findcloserepl(SP_remnants[ptn1], ptn1+1, false, true, HH_showerptns, HH_thermal);
4659         SP_remnants[ptn1].id(21);
4660       }else{loc = findcloserepl(SP_remnants[ptn1], ptn1+1, false, true, HH_showerptns, HH_thermal);}
4661 
4662       if(loc == 999999999 || loc > 0){
4663           int fid = (ran() > 0.33333333) ? ((ran() > 0.5) ? -1 : -2) : -3;
4664         HHparton fakep = SP_remnants[ptn1]; fakep.id(fid); fakep.set_color(0); fakep.set_anti_color(ptn1_col);
4665         if(std::abs(fakep.id()) < 3) {
4666           fakep.mass(xmq);
4667         } else {fakep.mass(xms);}
4668         double dir = (ran() < 0.5) ? 1. : -1.; double fake_pT = (p_fake >= 1.) ? 0.282842712474619 : 0.; double fake_phi = 2. * 3.14159265358979 * ran();
4669         fakep.px(fake_pT * cos(fake_phi)); fakep.py(fake_pT * sin(fake_phi));
4670         if (number_p_fake == 0 || number_p_fake == 2){
4671           fakep.pz(-p_fake);
4672         } else if (number_p_fake == 1 || number_p_fake == 3) {
4673           fakep.pz(p_fake);
4674         } else {fakep.pz(0.);}
4675         number_p_fake++;
4676         fakep.e(std::sqrt(fakep.px()*fakep.px() + fakep.py()*fakep.py() + fakep.pz()*fakep.pz() + fakep.mass()*fakep.mass()));
4677         fakep.orig(-1); fakep.is_remnant(true);
4678         fakep.is_fakeparton(true);
4679         SP_remnants.add(fakep);
4680       }else if(loc < 0){
4681         HH_thermal[-loc-1].acol(ptn1_col);
4682         HH_thermal[-loc-1].col(0);
4683         HH_thermal[-loc-1].is_used(true);
4684         HH_thermal[-loc-1].is_remnant(true);
4685         SP_remnants.add(HH_thermal[-loc-1]);
4686         SP_remnants[SP_remnants.num()-1].par(-loc-1);
4687       }
4688     }
4689     if(!anti_colors_match && (SP_remnants[ptn1].id() < 0 || SP_remnants[ptn1].id() == 21)) {
4690       int loc = 0;
4691       if(SP_remnants[ptn1].id() == 21){
4692         SP_remnants[ptn1].id(-1);
4693         loc = findcloserepl(SP_remnants[ptn1], ptn1+1, false, true, HH_showerptns, HH_thermal);
4694         SP_remnants[ptn1].id(21);
4695       }else{loc = findcloserepl(SP_remnants[ptn1], ptn1+1, false, true, HH_showerptns, HH_thermal);}
4696 
4697       if(loc == 999999999 || loc > 0){
4698           int fid = (ran() > 0.33333333) ? ((ran() > 0.5) ? 1 : 2) : 3;
4699         HHparton fakep = SP_remnants[ptn1]; fakep.id(fid); fakep.set_color(ptn1_acol); fakep.set_anti_color(0);
4700         if(std::abs(fakep.id()) < 3) {
4701           fakep.mass(xmq);
4702         } else {fakep.mass(xms);}
4703         double dir = (ran() < 0.5) ? 1. : -1.; double fake_pT = (p_fake >= 1.) ? 0.282842712474619 : 0.; double fake_phi = 2. * 3.14159265358979 * ran();
4704         fakep.px(fake_pT * cos(fake_phi)); fakep.py(fake_pT * sin(fake_phi));
4705         if (number_p_fake == 0 || number_p_fake == 2){
4706           fakep.pz(-p_fake);
4707         } else if (number_p_fake == 1 || number_p_fake == 3) {
4708           fakep.pz(p_fake);
4709         } else {fakep.pz(0.);}
4710         number_p_fake++;
4711         fakep.e(std::sqrt(fakep.px()*fakep.px() + fakep.py()*fakep.py() + fakep.pz()*fakep.pz() + fakep.mass()*fakep.mass()));
4712         fakep.orig(-1); fakep.is_remnant(true);
4713         fakep.is_fakeparton(true);
4714         SP_remnants.add(fakep);
4715       }else if(loc < 0){
4716         HH_thermal[-loc-1].col(ptn1_acol);
4717         HH_thermal[-loc-1].acol(0);
4718         HH_thermal[-loc-1].is_used(true);
4719         HH_thermal[-loc-1].is_remnant(true);
4720         SP_remnants.add(HH_thermal[-loc-1]);
4721         SP_remnants[SP_remnants.num()-1].par(-loc-1);
4722       }
4723     }
4724   }
4725 
4726   set_initial_parton_masses(SP_remnants);
4727 
4728   for(int ijunc=0; ijunc < Tempjunctions.size(); ++ijunc) { //Let's make Legs for Final string by verifying Tempjunctions! starting from the kind of junction(-1 or +1)
4729     //std::cout <<endl<<endl<<"  Let's see candidates for (anti)junction  "<<endl;
4730     //std::cout <<" Candidate " << ijunc+1 <<endl;
4731     //std::cout <<" [ (  " << Tempjunctions.at(ijunc).at(0).at(0) <<" , " << Tempjunctions.at(ijunc).at(0).at(1) <<" ), " ;
4732     //std::cout <<"  (  " << Tempjunctions.at(ijunc).at(1).at(0) <<" , " << Tempjunctions.at(ijunc).at(1).at(1) <<" ), " ;
4733     //std::cout <<"  (  " << Tempjunctions.at(ijunc).at(2).at(0) <<" , " << Tempjunctions.at(ijunc).at(2).at(1) <<" ), " ;
4734     //std::cout <<"  (  " << Tempjunctions.at(ijunc).at(3).at(0) <<" , " << Tempjunctions.at(ijunc).at(3).at(1) <<" ), " ;
4735     //std::cout <<" ] "<<endl;
4736 
4737     //std::cout <<endl<<" I'm Working !! from line 2027" <<endl;
4738     vector<int> correction; // for the case of 1 or 2 initiating particles, we need to remember the partons and get the used_junction tag to the original
4739     if(Tempjunctions.at(ijunc).at(0).at(0) == -1) { // check anti-color tags in SP_remnants partons!! to form anti-junction
4740       for(int irem=0; irem < SP_remnants.num(); ++irem) { // searching through all remnant particles
4741         //std::cout <<endl<<" Let's see " << irem+1 <<"th remnant particle with "<< "pid : " << SP_remnants[irem].pid() <<" color : "<< SP_remnants[irem].col()<< " anti-color : " << SP_remnants[irem].acol() <<endl;
4742         if(SP_remnants[irem].acol() == Tempjunctions.at(ijunc).at(1).at(1)){
4743           Leg1.push_back(SP_remnants[irem]);
4744           correction.push_back(irem);
4745           SP_remnants[irem].used_junction(true);
4746           //std::cout <<endl<<" Leg 1 has initiating particle " <<" and the pID is "<< SP_remnants[irem].pid()<<" and the color tag : "<<SP_remnants[irem].acol()<<endl<<endl;
4747           Legconsidering.push_back(irem);
4748         }
4749         if(SP_remnants[irem].acol() == Tempjunctions.at(ijunc).at(2).at(1)){
4750           Leg2.push_back(SP_remnants[irem]);
4751           correction.push_back(irem);
4752           SP_remnants[irem].used_junction(true);
4753           //std::cout <<endl<<" Leg 2 has initiating particle " <<" and the pID is "<< SP_remnants[irem].pid()<<" and the color tag : "<<SP_remnants[irem].acol()<<endl<<endl;
4754           Legconsidering.push_back(irem);
4755         }
4756         if(SP_remnants[irem].acol() == Tempjunctions.at(ijunc).at(3).at(1)){
4757           Leg3.push_back(SP_remnants[irem]);
4758           correction.push_back(irem);
4759           SP_remnants[irem].used_junction(true);
4760           //std::cout <<endl<<" Leg 3 has initiating particle " <<" and the pID is "<< SP_remnants[irem].pid()<<" and the color tag : "<<SP_remnants[irem].acol()<<endl<<endl;
4761           Legconsidering.push_back(irem);
4762         }
4763         if(Legconsidering.size() !=3 ){// if only one or two particles found in remnants, we need to set the tag to the original
4764           for(int icor = 0; icor < correction.size(); icor++){
4765             SP_remnants[correction.at(icor)].used_junction(false);
4766             //dignostic measure
4767             //std::cout <<endl<<"the "<<icor<<" th particle with color tag of "<<SP_remnants[icor].col()<<" , "<<SP_remnants[icor].acol()<<" are turned into unused particle"<<endl;
4768           }
4769           correction.clear();
4770         }
4771       }
4772     }else if(Tempjunctions.at(ijunc).at(0).at(0) == 1) { // check color tags in SP_remnants partons!! to form junction
4773       for(int irem=0; irem < SP_remnants.num(); ++irem) { // searching through all remnant particles
4774         //std::cout <<endl<<" Let's see " << irem+1 <<"th remnant particle with "<< "pid : " << SP_remnants[irem].pid() <<" color : "<< SP_remnants[irem].col()<< " anti-color : " << SP_remnants[irem].acol() <<endl;
4775         if(SP_remnants[irem].col() == Tempjunctions.at(ijunc).at(1).at(1)){
4776         Leg1.push_back(SP_remnants[irem]);
4777         correction.push_back(irem);
4778         SP_remnants[irem].used_junction(true);
4779         Legconsidering.push_back(irem);
4780         //std::cout <<endl<<" Leg 1 has initiating particle "<<" and the pID is "<< SP_remnants[irem].pid()<<" and the color tag : "<<SP_remnants[irem].col()<<endl<<endl;
4781         }
4782         if(SP_remnants[irem].col() == Tempjunctions.at(ijunc).at(2).at(1)){
4783           Leg2.push_back(SP_remnants[irem]);
4784           correction.push_back(irem);
4785           SP_remnants[irem].used_junction(true);
4786           //std::cout <<endl<<" Leg 2 has initiating particle " <<" and the pID is "<< SP_remnants[irem].pid()<<" and the color tag : "<<SP_remnants[irem].col()<<endl<<endl;
4787           Legconsidering.push_back(irem);
4788         }
4789         if(SP_remnants[irem].col() == Tempjunctions.at(ijunc).at(3).at(1)){
4790           Leg3.push_back(SP_remnants[irem]);
4791           correction.push_back(irem);
4792           SP_remnants[irem].used_junction(true);
4793           //std::cout <<endl<<" Leg 3 has initiating particle " <<" and the pID is "<< SP_remnants[irem].pid()<<" and the color tag : "<<SP_remnants[irem].col()<<endl<<endl;
4794           Legconsidering.push_back(irem);
4795         }
4796         if(Legconsidering.size() !=3 ){
4797           for(int icor = 0; icor < correction.size(); icor++){
4798             SP_remnants[correction.at(icor)].used_junction(false);
4799             //dignostic measure
4800             //std::cout <<endl<<"the "<<icor<<" th particle with color tag of "<<SP_remnants[icor].col()<<" , "<<SP_remnants[icor].acol()<<" are turned into unused particle"<<endl;
4801           }
4802           correction.clear();
4803         }
4804       }
4805     }
4806 
4807     if(Legconsidering.size() == 3) {
4808       realjuncindice.push_back(ijunc);
4809       //std::cout <<endl<<"the indice added for string repair : "<<ijunc<<endl;
4810       if(Tempjunctions.at(ijunc).at(0).at(0) == -1 && Leg1.at(0).col() != 0 && Leg1.at(0).acol() != 0){ // starting to form the Leg1 for anti_junction by Color Tag Tracing. If first particle is (anti)quark, no need to trace
4811         for(int iloop=0; iloop < SP_remnants.num(); iloop++){
4812           for(int icf = 0; icf < SP_remnants.num(); ++icf) {
4813             if( (Leg1.back().col() != 0) && (Leg1.back().col() == SP_remnants[icf].acol()) ){
4814               //std::cout <<endl<<"particle added to Leg 1 with color tag  ( "<<SP_remnants[icf].col() <<" and "<<SP_remnants[icf].acol()<<" ) "<<endl;
4815               Leg1.push_back(SP_remnants[icf]);
4816               SP_remnants[icf].used_junction(true);
4817             }
4818             if( Leg1.back().col() == 0 || Leg1.back().acol() == 0 ){ break; }
4819           }
4820         }
4821       }else if(Tempjunctions.at(ijunc).at(0).at(0) == 1 && Leg1.at(0).col() != 0 && Leg1.at(0).acol() != 0){ // starting to form the Leg1 junction by Color Tag Tracing. If first particle is quark, no need to trace
4822         for(int iloop=0; iloop < SP_remnants.num(); iloop++){
4823           for(int icf = 0; icf < SP_remnants.num(); ++icf) {
4824             if( (Leg1.back().acol() != 0) && (Leg1.back().acol() == SP_remnants[icf].col()) ){
4825               //std::cout <<endl<<"particle added to Leg 1 with color tag ( "<<SP_remnants[icf].col() <<" and "<<SP_remnants[icf].acol()<<" ) "<<endl;
4826               Leg1.push_back(SP_remnants[icf]);
4827               SP_remnants[icf].used_junction(true);
4828             }
4829             if(Leg1.back().col() == 0 || Leg1.back().acol() == 0){break;}
4830           }
4831         }
4832       }
4833 
4834       if(Tempjunctions.at(ijunc).at(0).at(0) == -1 && Leg2.at(0).col() != 0 && Leg2.at(0).acol() != 0){ // starting to form the Leg2 for anti_junction by Color Tag Tracing. If first particle is (anti)quark, no need to trace
4835         for(int iloop=0; iloop < SP_remnants.num(); iloop++){
4836           for(int icf = 0; icf < SP_remnants.num(); ++icf) {
4837             if(  ( Leg2.back().col() != 0 )  && (Leg2.back().col() == SP_remnants[icf].acol()) ){
4838               //std::cout <<endl<<"particle added to Leg 2 with color tag ( "<<SP_remnants[icf].col() <<" and "<<SP_remnants[icf].acol()<<" ) "<<endl;
4839               Leg2.push_back(SP_remnants[icf]);
4840               SP_remnants[icf].used_junction(true);
4841             }
4842             if( Leg2.back().col() == 0 || Leg2.back().acol() == 0){break;}
4843           }
4844         }
4845       }else if(Tempjunctions.at(ijunc).at(0).at(0) == 1 && Leg2.at(0).col() != 0 && Leg2.at(0).acol() != 0){ // starting to form the Leg2 junction by Color Tag Tracing. If first particle is quark, no need to trace
4846         for(int iloop=0; iloop < SP_remnants.num(); iloop++){
4847           for(int icf = 0; icf < SP_remnants.num(); ++icf) {
4848             if(   (Leg2.back().acol() != 0) && (Leg2.back().acol() == SP_remnants[icf].col())  ){
4849               //std::cout <<endl<<"particle added to Leg 2 with color tag ( "<<SP_remnants[icf].col() <<" and "<<SP_remnants[icf].acol()<<" ) "<<endl;
4850               Leg2.push_back(SP_remnants[icf]);
4851               SP_remnants[icf].used_junction(true);
4852             }
4853             if( Leg2.back().col() == 0 || Leg2.back().acol() == 0){break;}
4854           }
4855         }
4856       }
4857 
4858       if(Tempjunctions.at(ijunc).at(0).at(0) == -1 && Leg3.at(0).col() != 0 && Leg3.at(0).acol() != 0){ // starting to form the Leg3 for anti_junction by Color Tag Tracing. If first particle is (anti)quark, no need to trace
4859         for(int iloop=0; iloop < SP_remnants.num(); iloop++){
4860           for(int icf = 0; icf < SP_remnants.num(); ++icf) {
4861             if(  (Leg3.back().col() != 0) && (Leg3.back().col() == SP_remnants[icf].acol()) ){
4862               //std::cout <<endl<<"particle added to Leg 3 with color tag ( "<<SP_remnants[icf].col() <<" and "<<SP_remnants[icf].acol()<<" ) "<<endl;
4863               Leg3.push_back(SP_remnants[icf]);
4864               SP_remnants[icf].used_junction(true);
4865             }
4866             if( Leg3.back().col() == 0 || Leg3.back().acol() == 0){break;}
4867           }
4868         }
4869       }else if(Tempjunctions.at(ijunc).at(0).at(0) == 1 && Leg3.at(0).col() != 0 && Leg3.at(0).acol() != 0){ // starting to form the Leg3 junction by Color Tag Tracing. If first particle is quark, no need to trace
4870         for(int iloop=0; iloop < SP_remnants.num(); iloop++){
4871           for(int icf = 0; icf < SP_remnants.num(); ++icf) {
4872             //std::cout <<"candidate particle is "<<SP_remnants[icf].pid()<<" , "<<SP_remnants[icf].col()<<" , "<<SP_remnants[icf].acol()<<" , "<<SP_remnants[icf].used_junction()<<endl;
4873             //std::cout <<"and standard particle is "<<Leg3.back().pid()<<" , "<<Leg3.back().col()<<" , "<<Leg3.back().acol()<<" , "<<Leg3.back().used_junction()<<endl;
4874             if( (Leg3.back().acol() != 0) && (Leg3.back().acol() == SP_remnants[icf].col()) ){
4875               //std::cout <<endl<<"particle added to Leg 3 with color tag ( "<<SP_remnants[icf].col() <<" and "<<SP_remnants[icf].acol()<<" ) "<<endl;
4876               Leg3.push_back(SP_remnants[icf]);
4877               SP_remnants[icf].used_junction(true);
4878             }
4879             if( Leg3.back().col() == 0 || Leg3.back().acol() == 0 ){break;}
4880           }
4881         }
4882       }
4883          JuncLegs.push_back(Leg1);
4884          JuncLegs.push_back(Leg2);
4885          JuncLegs.push_back(Leg3);
4886          JuncStructure.push_back(JuncLegs); // now junction structure with three complete legs is saved, so clear previous infos for considering next junction candidate.
4887     }
4888     JuncLegs.clear();
4889     Leg1.clear();
4890     Leg2.clear();
4891     Leg3.clear();
4892     Legconsidering.clear();
4893   }
4894 
4895   //So far, all the information for (Anti)Junction and Legs are formed by color tag tracing. Let's Check this out
4896   //dignostic measure
4897   /*for(int ijuncstr=0; ijuncstr < JuncStructure.size(); ++ijuncstr) {
4898     std::cout <<endl<<endl<<"  Let's see Temporary junction structure   "<<endl;
4899     std::cout <<" Temp Junction :" << ijuncstr+1 <<endl;
4900     std::cout <<"Leg 1 : [ ";
4901     for(int ileg1=0; ileg1 < JuncStructure.at(ijuncstr).at(0).size(); ++ileg1){
4902       std::cout <<" (  " << JuncStructure.at(ijuncstr).at(0)[ileg1].col() <<" , " << JuncStructure.at(ijuncstr).at(0)[ileg1].acol() <<" ), " ;
4903     }
4904     std::cout <<" ] " <<endl;
4905     std::cout <<"Leg 2 : [ ";
4906     for(int ileg2=0; ileg2 < JuncStructure.at(ijuncstr).at(1).size(); ++ileg2){
4907       std::cout <<" (  " << JuncStructure.at(ijuncstr).at(1)[ileg2].col() <<" , " << JuncStructure.at(ijuncstr).at(1)[ileg2].acol() <<" ), " ;
4908     }
4909     std::cout <<" ] " <<endl;
4910     std::cout <<"Leg 3 : [ ";
4911     for(int ileg3=0; ileg3 < JuncStructure.at(ijuncstr).at(2).size(); ++ileg3){
4912       std::cout <<" (  " << JuncStructure.at(ijuncstr).at(2)[ileg3].col() <<" , " << JuncStructure.at(ijuncstr).at(2)[ileg3].acol() <<" ), " ;
4913     }
4914     std::cout <<" ] " <<endl;
4915   }*/
4916 
4917   // Now, we will find the shared legs and sorting them into the corresponding vectors, the information from JuncStructure vector and realjuncindice vector work together here.
4918   // if the tags of first particle in a string and end particle in another string are same, they are shared Leg!!
4919   for(int irep1 = 0; irep1 < JuncStructure.size(); irep1++){
4920     IMStructure3.push_back(realjuncindice.at(irep1));
4921     IMStructure3.push_back(Tempjunctions.at(realjuncindice.at(irep1)).at(0).at(0));
4922     IMStructure3.push_back(irep1);// room for other usage
4923     IMStructure3.push_back(0); // tag 1: dijinction, tag0: other cases
4924     IMStructure2.push_back(IMStructure3);
4925     IMStructure3.clear();
4926     for(int irep2 = 0; irep2 < 3; irep2++){
4927       for(int irep3 = 0; irep3 < JuncStructure.size(); irep3++){
4928         for(int irep4 = 0;  irep4 < 3; irep4++){
4929           if( (irep1 != irep3) && (JuncStructure.at(irep1).at(irep2).at(0).col() == JuncStructure.at(irep3).at(irep4).back().col()) &&
4930             (JuncStructure.at(irep1).at(irep2).at(0).acol() == JuncStructure.at(irep3).at(irep4).back().acol())){
4931             IMStructure3.push_back(irep1);
4932             IMStructure3.push_back(irep2);
4933             IMStructure3.push_back(irep3);
4934             IMStructure3.push_back(irep4); // the first pair means irep2_th Leg in irep1_th junction is linked with irep4_th Leg in irep3_th Tempjunction
4935             IMStructure2.push_back(IMStructure3);
4936             IMStructure3.clear();
4937           }
4938         }
4939       }
4940     }
4941     IMStructure1.push_back(IMStructure2);
4942     IMStructure2.clear();
4943   }
4944 
4945   //dignostic measure!
4946   /*JSINFO << "First IMStructure printout";
4947   std::cout <<endl;
4948   for(int icheck1 = 0; icheck1 < IMStructure1.size(); icheck1++){
4949     for(int icheck2 = 0; icheck2 < IMStructure1.at(icheck1).size(); icheck2++){
4950       std::cout <<" ( ";
4951       for(int icheck3 = 0; icheck3 < IMStructure1.at(icheck1).at(icheck2).size(); icheck3++){
4952         std::cout <<IMStructure1.at(icheck1).at(icheck2).at(icheck3)<<" , ";
4953       }
4954       std::cout <<" ) ";
4955     }
4956     std::cout <<endl;
4957   }*/
4958 
4959   // create a vector containing 0 if the (anti-)junction contains only shower partons, 1 if at least one thermal
4960   // this is only for the ones in Recombearly1
4961   std::vector<int> thermal_parton_junction;
4962 
4963   //since the relation between junctions is defined, Let's sorting Junctions based on shared legs
4964   for(int iloop1 = 0; iloop1 < IMStructure1.size(); iloop1++){
4965     //structure for 3-shared particles find shared legs and tossing them into the baryon formation
4966     if(IMStructure1.at(iloop1).size() == 4){
4967       for(int iloop2 = 1; iloop2 < IMStructure1.at(iloop1).size(); iloop2++){
4968         for(int iloop3 = 0; iloop3 < IMStructure1.size(); iloop3++){
4969           for(int iloop4 = 1; iloop4 < IMStructure1.at(iloop3).size(); iloop4++){
4970             if( (IMStructure1.at(iloop1).at(iloop2).at(2) == IMStructure1.at(iloop3).at(iloop4).at(0)) &&
4971               (IMStructure1.at(iloop1).at(iloop2).at(3) == IMStructure1.at(iloop3).at(iloop4).at(1))  ){
4972               vector<int> testing;
4973               testing.push_back(IMStructure1.at(iloop1).at(iloop2).at(2));
4974               testing.push_back(IMStructure1.at(iloop1).at(iloop2).at(3));
4975               testing.push_back(IMStructure1.at(iloop1).at(iloop2).at(0));
4976               testing.push_back(IMStructure1.at(iloop1).at(iloop2).at(1)); //now temporary vector is created by this procedure.
4977               std::vector<vector<int>>::iterator it = std::find(IMStructure1.at(iloop3).begin(), IMStructure1.at(iloop3).end(), testing);
4978               IMStructure1.at(iloop3).erase(it);
4979               testing.clear(); //now the one of the leg is eliminated in the list, so there is no overlapped leg to be tossed into baryon formation list.
4980             }
4981             if((JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(0)).at(IMStructure1.at(iloop1).at(iloop2).at(1)).at(0).col() != 0) &&
4982                (JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(0)).at(IMStructure1.at(iloop1).at(iloop2).at(1)).at(0).acol() != 0) &&
4983                (JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(2)).at(IMStructure1.at(iloop1).at(iloop2).at(3)).back().col() != 0) &&
4984                (JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(2)).at(IMStructure1.at(iloop1).at(iloop2).at(3)).back().acol() != 0)) {
4985               parton_collection tempqpair;
4986               gluon_decay(JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(0)).at(IMStructure1.at(iloop1).at(iloop2).at(1)).at(0), tempqpair ); // the first particle has col tag and the second had acol tag
4987               //std::vector<HHparton>::iterator tempit1 = JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(0)).at(IMStructure1.at(iloop1).at(iloop2).at(1)).begin();
4988               //JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(0)).at(IMStructure1.at(iloop1).at(iloop2).at(1)).erase(tempit1);
4989               if(IMStructure1.at(iloop1).at(0).at(1) == -1){
4990                 Recombearly2.push_back(tempqpair[1]); //add anti-particle to form anti baryon
4991                 //std::cout <<endl<<" the particle with tags { "<< JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(2)).at(IMStructure1.at(iloop1).at(iloop2).at(3)).back().col()<<" , "
4992                 //<<JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(2)).at(IMStructure1.at(iloop1).at(iloop2).at(3)).back().acol()<<" } is changed into ";
4993                 JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(2)).at(IMStructure1.at(iloop1).at(iloop2).at(3)).pop_back();
4994                 JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(2)).at(IMStructure1.at(iloop1).at(iloop2).at(3)).push_back(tempqpair[0]); // add remain parton to the original leg
4995                 //std::cout <<" { " << tempqpair[0].col()<<" , "<< tempqpair[0].acol()<<" }"<<endl;
4996                 //std::cout <<" and "<<" { " << tempqpair[1].col()<<" , "<< tempqpair[1].acol()<<" } "<<" is gone to be recombined"<<endl;
4997               }
4998               if(IMStructure1.at(iloop1).at(0).at(1) == 1){
4999                 Recombearly2.push_back(tempqpair[0]); //add particle to form baryon
5000                 //std::cout <<endl<<" the particle with tags { "<< JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(2)).at(IMStructure1.at(iloop1).at(iloop2).at(3)).back().col()<<" , "
5001                 //<<JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(2)).at(IMStructure1.at(iloop1).at(iloop2).at(3)).back().acol()<<" } is changed into ";
5002                 JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(2)).at(IMStructure1.at(iloop1).at(iloop2).at(3)).pop_back();
5003                 JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(2)).at(IMStructure1.at(iloop1).at(iloop2).at(3)).push_back(tempqpair[1]); // add remain parton to the original leg
5004                 //std::cout <<" { " << tempqpair[0].col()<<" , "<< tempqpair[0].acol()<<" }"<<endl;
5005                 //std::cout <<" and "<<" { " << tempqpair[1].col()<<" , "<< tempqpair[1].acol()<<" } "<<" is gone to be recombined"<<endl;
5006               }
5007               tempqpair.clear();
5008             }
5009           }
5010         }
5011       }
5012       thermal_parton_junction.push_back(Tempjunctions.at(IMStructure1.at(iloop1).at(0).at(2)).at(0).at(1));
5013       IMStructure1.erase(IMStructure1.begin()+iloop1); // erase the junction with three shared legs from the IMStructure
5014       iloop1--;
5015       Recombearly1.push_back(Recombearly2);
5016       Recombearly2.clear();
5017     }
5018   }
5019 
5020   //One thing to remind : JuncStructure has information of parton class, and IMStructure has informations about these partons or junctions with same indice with JuncStructure
5021   for(int iloop1 = 0; iloop1 < IMStructure1.size(); iloop1++){
5022     if(IMStructure1.at(iloop1).size() == 3){ // 2-shared leg case {basic info, shared leg1's info, shared leg2's info}
5023       // loop for pop out the unshared leg in the junction structure.
5024       int leftleg; // indice of unshared leg which will remain after the Early recombinaton
5025       int SI = 0; // Sum of the Indice of Leg{if 1 = 0+1, Leg3 is not shared, if 3 = 1+2, Leg 0 is not shared}
5026       for(int itail = 1; itail < IMStructure1.at(iloop1).size(); itail++){
5027         SI = SI + IMStructure1.at(iloop1).at(itail).at(1);
5028       }
5029       //std::cout <<endl<<"SI = "<<SI<<endl;
5030       vector<int> indicevec; // vector for indice, we could use if statement, but when if and for statement are repeated, possibly forced execution occurs regardless of if statement, so take most defensive measure.
5031       indicevec.push_back(2);
5032       indicevec.push_back(1);
5033       indicevec.push_back(0);
5034       leftleg = indicevec[SI-1];
5035       //below was tested, but showed forced execution{that is all of the Three statements executed so that left leg was always 0}
5036       //if(SI = 1 ){ leftleg = 2; SI = 0;}
5037       //if(SI = 2 ){ leftleg = 1; SI = 0;}
5038       //if(SI = 3 ){ leftleg = 0; SI = 0;}
5039       //std::cout <<endl<<"leftleg number is "<<leftleg<<endl;
5040 
5041       int jidentity = IMStructure1.at(iloop1).at(0).at(1); //junction identity 1 or -1 {junction or anti juncttion}
5042       //std::cout <<endl<<"junction identity is "<<jidentity<<endl;
5043       int juncnum = IMStructure1.at(iloop1).at(0).at(0); //junction number to be dealt with
5044       vector<HHparton> tempstring = JuncStructure.at(juncnum).at(leftleg); //declare the unshared leg.
5045       if(jidentity == 1 && tempstring.at(0).col() != 0 && tempstring.at(0).acol() != 0){
5046         parton_collection tempqpair;
5047         gluon_decay( tempstring.at(0), tempqpair);
5048         tempstring.erase(tempstring.begin());
5049         tempstring.insert(tempstring.begin() , tempqpair[1] );
5050         Tailoredstring1.push_back(tempstring);
5051         Recombearly2.push_back(tempqpair[0]);
5052       }else if(jidentity == -1 && tempstring.at(0).col() != 0 && tempstring.at(0).acol() != 0){
5053         parton_collection tempqpair;
5054         gluon_decay( tempstring.at(0), tempqpair);
5055         tempstring.erase(tempstring.begin());
5056         tempstring.insert(tempstring.begin() , tempqpair[0] );
5057         Tailoredstring1.push_back(tempstring);
5058         Recombearly2.push_back(tempqpair[1]);
5059       }else{
5060         Recombearly2.push_back(tempstring.at(0));
5061       }
5062       indicevec.clear();
5063 
5064       for(int iloop2 = 1; iloop2 < IMStructure1.at(iloop1).size(); iloop2++){
5065         for(int iloop3 = 0; iloop3 < IMStructure1.size(); iloop3++){
5066           for(int iloop4 = 1; iloop4 < IMStructure1.at(iloop3).size(); iloop4++){
5067             if( (IMStructure1.at(iloop1).at(iloop2).at(2) == IMStructure1.at(iloop3).at(iloop4).at(0)) &&
5068               (IMStructure1.at(iloop1).at(iloop2).at(3) == IMStructure1.at(iloop3).at(iloop4).at(1))  ){
5069               vector<int> testing;
5070               testing.push_back(IMStructure1.at(iloop1).at(iloop2).at(2));
5071               testing.push_back(IMStructure1.at(iloop1).at(iloop2).at(3));
5072               testing.push_back(IMStructure1.at(iloop1).at(iloop2).at(0));
5073               testing.push_back(IMStructure1.at(iloop1).at(iloop2).at(1)); //now temporary vector is created by this procedure.
5074               std::vector<vector<int>>::iterator it = std::find(IMStructure1.at(iloop3).begin(), IMStructure1.at(iloop3).end(), testing);
5075               IMStructure1.at(iloop3).erase(it);
5076               testing.clear(); //now the one of the leg is eliminated in the list, so there is no overlapped leg to be tossed into baryon formation list.
5077             }
5078             if((JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(0)).at(IMStructure1.at(iloop1).at(iloop2).at(1)).at(0).col() != 0) &&
5079                (JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(0)).at(IMStructure1.at(iloop1).at(iloop2).at(1)).at(0).acol() != 0) &&
5080                (JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(2)).at(IMStructure1.at(iloop1).at(iloop2).at(3)).back().col() != 0) &&
5081                (JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(2)).at(IMStructure1.at(iloop1).at(iloop2).at(3)).back().acol() != 0)) {
5082               parton_collection tempqpair;
5083               gluon_decay(JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(0)).at(IMStructure1.at(iloop1).at(iloop2).at(1)).at(0), tempqpair ); // the first particle has col tag and the second had acol tag
5084               //std::vector<HHparton>::iterator tempit1 = JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(0)).at(IMStructure1.at(iloop1).at(iloop2).at(1)).begin();
5085               //JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(0)).at(IMStructure1.at(iloop1).at(iloop2).at(1)).erase(tempit1);
5086               if(IMStructure1.at(iloop1).at(0).at(1) == -1){
5087                 Recombearly2.push_back(tempqpair[1]); //add anti-particle to form anti baryon
5088                 //std::cout <<endl<<" the particle with tags { "<< JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(2)).at(IMStructure1.at(iloop1).at(iloop2).at(3)).back().col()<<" , "
5089                 //<<JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(2)).at(IMStructure1.at(iloop1).at(iloop2).at(3)).back().acol()<<" } is changed into ";
5090                 JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(2)).at(IMStructure1.at(iloop1).at(iloop2).at(3)).pop_back();
5091                 JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(2)).at(IMStructure1.at(iloop1).at(iloop2).at(3)).push_back(tempqpair[0]); // add remain parton to the original leg
5092                 //std::cout <<" { " << tempqpair[0].col()<<" , "<< tempqpair[0].acol()<<" }"<<endl;
5093                 //std::cout <<" and "<<" { " << tempqpair[1].col()<<" , "<< tempqpair[1].acol()<<" } "<<" is gone to be recombined"<<endl;
5094               }
5095               if(IMStructure1.at(iloop1).at(0).at(1) == 1){
5096                 Recombearly2.push_back(tempqpair[0]); //add particle to form baryon
5097                 //std::cout <<endl<<" the particle with tags { "<< JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(2)).at(IMStructure1.at(iloop1).at(iloop2).at(3)).back().col()<<" , "
5098                 //<<JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(2)).at(IMStructure1.at(iloop1).at(iloop2).at(3)).back().acol()<<" } is changed into ";
5099                 JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(2)).at(IMStructure1.at(iloop1).at(iloop2).at(3)).pop_back();
5100                 JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(2)).at(IMStructure1.at(iloop1).at(iloop2).at(3)).push_back(tempqpair[1]); // add remain parton to the original leg
5101                 //std::cout <<" { " << tempqpair[0].col()<<" , "<< tempqpair[0].acol()<<" }"<<endl;
5102                 //std::cout <<" and "<<" { " << tempqpair[1].col()<<" , "<< tempqpair[1].acol()<<" } "<<" is gone to be recombined"<<endl;
5103               }
5104             }
5105           }
5106         }
5107       }
5108       thermal_parton_junction.push_back(Tempjunctions.at(IMStructure1.at(iloop1).at(0).at(2)).at(0).at(1));
5109       IMStructure1.erase(IMStructure1.begin()+iloop1); // erase the junction with three shared legs from the IMStructure
5110       iloop1--;
5111       Recombearly1.push_back(Recombearly2);
5112       Recombearly2.clear();
5113     }
5114   }
5115 
5116   /*std::cout <<endl;
5117   std::cout <<" number of early recombined baryons 1: "<<Recombearly1.size()<<endl;
5118   for(int ibary1 = 0; ibary1 < Recombearly1.size(); ibary1++){
5119     std::cout <<"the "<< ibary1 <<" st baryon is made of ";
5120     for(int ibary2 = 0; ibary2 < Recombearly1.at(ibary1).size(); ibary2++){
5121       std::cout <<" { "<<Recombearly1.at(ibary1).at(ibary2).col()<<" , "<< Recombearly1.at(ibary1).at(ibary2).acol()  <<" } , ";
5122     }
5123     std::cout <<endl;
5124   }*/
5125 
5126   //dignostic measure{IMStructure1}
5127   /*JSINFO << "1.5 IMStructure printout";
5128   std::cout <<endl;
5129   for(int icheck1 = 0; icheck1 < IMStructure1.size(); icheck1++){
5130     for(int icheck2 = 0; icheck2 < IMStructure1.at(icheck1).size(); icheck2++){
5131       std::cout <<" ( ";
5132       for(int icheck3 = 0; icheck3 < IMStructure1.at(icheck1).at(icheck2).size(); icheck3++){
5133         std::cout <<IMStructure1.at(icheck1).at(icheck2).at(icheck3)<<" , ";
5134       }
5135       std::cout <<" ) ";
5136     }
5137     std::cout <<endl;
5138   }*/
5139 
5140   for(int iloop1 = 0; iloop1 < IMStructure1.size(); iloop1++){
5141     if(IMStructure1.at(iloop1).size() == 2 && IMStructure1.at(iloop1).at(0).at(3) == 0){ // Dijunction Structure
5142       for(int iloop2 = 1; iloop2< IMStructure1.at(iloop1).size(); iloop2++){
5143         for(int iloop3 = 0; iloop3 < IMStructure1.size(); iloop3++){
5144           for(int iloop4 = 1; iloop4 < IMStructure1.at(iloop3).size(); iloop4++){
5145             if( (IMStructure1.at(iloop1).at(iloop2).at(2) == IMStructure1.at(iloop3).at(iloop4).at(0)) &&
5146               (IMStructure1.at(iloop1).at(iloop2).at(3) == IMStructure1.at(iloop3).at(iloop4).at(1))  ){ // the case where we found the shared legs pair.
5147               if(IMStructure1.at(iloop1).at(0).at(3) == 0) {
5148                 for(int idijunc1 = 0; idijunc1 < 3; idijunc1++){ // first, put three legs of first junction
5149                   Dijunction2.push_back(JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(0)).at(idijunc1));
5150                 }
5151                 for(int idijunc2 = 0; idijunc2 < 3; idijunc2++){ // second, exclude shared leg in second junction to be merged
5152                   if( idijunc2 != IMStructure1.at(iloop1).at(iloop2).at(3)){
5153                     Dijunction2.push_back(JuncStructure.at(IMStructure1.at(iloop1).at(iloop2).at(2)).at(idijunc2));
5154                   }
5155                 }
5156               }
5157               Dijunction1.push_back(Dijunction2); //finally, five legs are added in the vector to form dijunction structure.
5158               Dijunction2.clear(); // clear temp vector for next procedure.
5159               IMStructure1.at(iloop1).at(0).pop_back();
5160               IMStructure1.at(iloop1).at(0).push_back(1); // tag representing dijunction structure.
5161               IMStructure1.at(iloop3).at(0).pop_back();
5162               IMStructure1.at(iloop3).at(0).push_back(1); // tag representing dijunction structure.
5163 
5164               vector<int> testing;
5165               testing.push_back(IMStructure1.at(iloop1).at(iloop2).at(2));
5166               testing.push_back(IMStructure1.at(iloop1).at(iloop2).at(3));
5167               testing.push_back(IMStructure1.at(iloop1).at(iloop2).at(0));
5168               testing.push_back(IMStructure1.at(iloop1).at(iloop2).at(1)); //now temporary vector is created by this procedure.
5169               std::vector<vector<int>>::iterator it = std::find(IMStructure1.at(iloop3).begin(), IMStructure1.at(iloop3).end(), testing);
5170               IMStructure1.at(iloop3).erase(it);
5171               testing.clear();
5172               //now the one of the leg is eliminated in the list, so there is no overlapped leg to be tossed into baryon formation list.
5173             }
5174           }
5175         }
5176       }
5177     }
5178   }
5179 
5180   //dignostic measure{IMStructure1}
5181   /*JSINFO << "1.75 IMStructure printout";
5182   std::cout <<endl;
5183   for(int icheck1 = 0; icheck1 < IMStructure1.size(); icheck1++){
5184     for(int icheck2 = 0; icheck2 < IMStructure1.at(icheck1).size(); icheck2++){
5185       std::cout <<" ( ";
5186       for(int icheck3 = 0; icheck3 < IMStructure1.at(icheck1).at(icheck2).size(); icheck3++){
5187         std::cout <<IMStructure1.at(icheck1).at(icheck2).at(icheck3)<<" , ";
5188       }
5189       std::cout <<" ) ";
5190     }
5191     std::cout <<endl;
5192   }*/
5193 
5194   for(int irepair = 0; irepair < IMStructure1.size(); irepair++) {
5195     if(IMStructure1.at(irepair).size() == 1 && IMStructure1.at(irepair).at(0).at(3) == 0  ){ // size one means there are no shared legs to the junction, so put them directly to the single junction vector
5196       Singlejunction2.push_back(JuncStructure.at(IMStructure1.at(irepair).at(0).at(2)).at(0));
5197       Singlejunction2.push_back(JuncStructure.at(IMStructure1.at(irepair).at(0).at(2)).at(1));
5198       Singlejunction2.push_back(JuncStructure.at(IMStructure1.at(irepair).at(0).at(2)).at(2));
5199       Singlejunction1.push_back(Singlejunction2);
5200       Singlejunction2.clear();
5201     }//After all, all these vectors of junction legs will be tossed into PYTHIA to be hadronized. before that we need to set Mother Daughter tag for PYTHIA
5202   } // collecting all single junctions
5203 
5204   //dignostic measure{IMStructure1}
5205   /*JSINFO << "Second IMStructure printout";
5206   std::cout <<endl;
5207   for(int icheck1 = 0; icheck1 < IMStructure1.size(); icheck1++){
5208     for(int icheck2 = 0; icheck2 < IMStructure1.at(icheck1).size(); icheck2++){
5209       std::cout <<" ( ";
5210       for(int icheck3 = 0; icheck3 < IMStructure1.at(icheck1).at(icheck2).size(); icheck3++){
5211         std::cout <<IMStructure1.at(icheck1).at(icheck2).at(icheck3)<<" , ";
5212       }
5213       std::cout <<" ) ";
5214     }
5215     std::cout <<endl;
5216   }*/
5217 
5218   //now we need to form fake partons and baryons for appending particles to PYTHIA{for Dijunction Structure}
5219   //declaration of required Variables
5220   bool J = false;
5221   bool antiJ = false;
5222   bool bothJ = false;
5223   for(int idj1 = 0; idj1 < Dijunction1.size(); idj1++){ //searching dijunction
5224     for(int idj2 = 0; idj2 < Dijunction1.at(idj1).size(); idj2++){ //searching dijunction's leg
5225       //std::cout <<endl<<"let's check these particles "<<endl;
5226       //std::cout <<" { "<<Dijunction1.at(idj1).at(idj2).at(0).col()<<" , "<<Dijunction1.at(idj1).at(idj2).at(0).acol()<<" } "<<endl;
5227       //std::cout <<" { "<<Dijunction1.at(idj1).at(idj2).back().col()<<" , "<<Dijunction1.at(idj1).at(idj2).back().acol()<<" } "<<endl;
5228       for(int itpj1 = 0; itpj1 < IMStructure1.size(); itpj1++){ //searching Tempjunction
5229         for(int itpj2 = 1; itpj2 < Tempjunctions.at(itpj1).size(); itpj2++){ //searching color tags in tempjunction{ {_+1, 0 }, {_+1, tag1}, {_+1, tag2}, {_+1, tag3} }
5230           if(Dijunction1.at(idj1).at(idj2).at(0).col() == Tempjunctions.at(IMStructure1.at(itpj1).at(0).at(0)).at(itpj2).at(1) || //check whether first or last particle has correponding color tags for J
5231             Dijunction1.at(idj1).at(idj2).back().col() == Tempjunctions.at(IMStructure1.at(itpj1).at(0).at(0)).at(itpj2).at(1) ){
5232             J = true;
5233           }
5234           if(Dijunction1.at(idj1).at(idj2).at(0).acol() == Tempjunctions.at(IMStructure1.at(itpj1).at(0).at(0)).at(itpj2).at(1) || //check whether first or last particle has correponding color tags for J
5235             Dijunction1.at(idj1).at(idj2).back().acol() == Tempjunctions.at(IMStructure1.at(itpj1).at(0).at(0)).at(itpj2).at(1) ){
5236             antiJ = true;
5237           }
5238         }
5239       }
5240       if(J == true && antiJ == false){ // this leg is a part of junction
5241         DijunctionInfo2.push_back(1);
5242       }
5243       if(J == false && antiJ == true){ // this leg is a part of junction
5244         DijunctionInfo2.push_back(-1);
5245       }
5246       if(J == true && antiJ == true){
5247         bothJ = true;
5248       }
5249       if(bothJ){ //this leg is shared leg, so that fake parton shoud be added after all
5250         DijunctionInfo2.push_back(0);
5251       }
5252       J = false; //reseting variables to check other legs in Dijunction structure
5253       antiJ = false;
5254       bothJ = false;
5255     }
5256     DijunctionInfo1.push_back(DijunctionInfo2);
5257     DijunctionInfo2.clear();
5258   }//so far, vector about the information of dijunction structure is formed,{ so, we could put identity 1-leg first, and put identity-0 leg and -1 leg}
5259   //based on the information above, we need to add fake partons, which are used for telling pythia about the color flow{fake particle id is ignored, since we'll set
5260   // negative status flag}, with this color flow information, PYTHIA can detect J and anti-J
5261 
5262   //additional proceudre to change the configuration of shared leg by searching through dijunction1 and dijunction1info vectors
5263   // make sure that the shared leg is ordered from junction to antijunction, used later
5264   for(int ileg1 = 0 ; ileg1 < Dijunction1.size(); ileg1++){
5265     for(int ileg2 = 0; ileg2 < Dijunction1.at(ileg1).size(); ileg2++){
5266       bool needflip = false;
5267       if((DijunctionInfo1.at(ileg1).at(ileg2) == 0 && Dijunction1.at(ileg1).at(ileg2).size() != 1) &&
5268         (Dijunction1.at(ileg1).at(ileg2).at(0).col() == Dijunction1.at(ileg1).at(ileg2).at(1).acol()) ){ // In this case, we need to flip the order of the partons in this shared leg
5269         needflip = true;
5270       }
5271       if(needflip){
5272         std::reverse(Dijunction1.at(ileg1).at(ileg2).begin() , Dijunction1.at(ileg1).at(ileg2).end() );
5273       }
5274       needflip = false;
5275     }
5276   }
5277 
5278   //dignostic measure{DijunctionInfo1}
5279   /*std::cout <<endl;
5280   std::cout <<" DijunctionInfo Checking"<<endl;
5281   for(int icheck1 = 0; icheck1 < DijunctionInfo1.size(); icheck1++){
5282     std::cout <<" Let's Check all the elements! : ";
5283     for(int icheck2 = 0; icheck2 < DijunctionInfo1.at(icheck1).size(); icheck2++){
5284       std::cout <<DijunctionInfo1.at(icheck1).at(icheck2)<<" , ";
5285     }
5286     std::cout <<endl;
5287   }*/
5288 
5289   //dignostic measure{Dijunction1}
5290   /*std::cout <<endl;
5291   std::cout <<" List of Dijunction Structure"<<endl;
5292   for(int icheck1 = 0; icheck1 < Dijunction1.size(); icheck1++){
5293     std::cout <<" Dijunction : "<<icheck1<<endl;
5294     for(int icheck2 = 0 ; icheck2 < Dijunction1.at(icheck1).size(); icheck2++){
5295       std::cout <<" Leg "<<icheck2<<" : "<<"{ identity : "<< DijunctionInfo1.at(icheck1).at(icheck2)<<" }  ";
5296       for(int icheck3 = 0; icheck3 < Dijunction1.at(icheck1).at(icheck2).size(); icheck3++){
5297         std::cout <<" ( "<<Dijunction1.at(icheck1).at(icheck2).at(icheck3).col()<<" , "<<Dijunction1.at(icheck1).at(icheck2).at(icheck3).acol()<< " )  ";
5298       }
5299       std::cout <<endl;
5300     }
5301   }*/
5302 
5303   //dignostic measure{Singlejunction1}
5304   /*std::cout <<endl;
5305   std::cout <<" List of Single Junction Structure"<<endl;
5306   for(int icheck1 = 0; icheck1 < Singlejunction1.size(); icheck1++){
5307     std::cout <<" Single junction : "<<icheck1<<endl;
5308     for(int icheck2 = 0 ; icheck2 < Singlejunction1.at(icheck1).size(); icheck2++){
5309       std::cout <<" Leg "<<icheck2<<" : ";
5310       for(int icheck3 = 0; icheck3 < Singlejunction1.at(icheck1).at(icheck2).size(); icheck3++){
5311         std::cout <<" ( "<<Singlejunction1.at(icheck1).at(icheck2).at(icheck3).col()<<" , "<<Singlejunction1.at(icheck1).at(icheck2).at(icheck3).acol()<< " )  ";
5312       }
5313       std::cout <<endl;
5314     }
5315   }*/
5316 
5317   //For the validity with PYTHIA running, each Leg in Single or Dijunction Structure should have q or q-bar as endpoint particle, so checking whether the gluon is located at the endpoint of the Leg
5318   //Starting from Leg's in single junction.
5319   for(int is1 = 0; is1 < Singlejunction1.size(); is1++){
5320     HHparton p1 = Singlejunction1.at(is1).at(0).back(); //endpoint particle of first leg in is1_st Singlejunction1
5321     HHparton p2 = Singlejunction1.at(is1).at(1).back(); //endpoint particle of second leg in is1_st Singlejunction1
5322     HHparton p3 = Singlejunction1.at(is1).at(2).back(); //endpoint particle of third leg in is1_st Singlejunction1
5323 
5324     // basically, assume the junction. but check the id's of them and change identity of the condition for antijunction is meeted
5325     bool ajunction = false;
5326 
5327     if( p1.id() < 0 || p2.id() < 0 || p3.id() < 0){
5328       ajunction = true;
5329     }
5330 
5331     for(int is2 = 0; is2 < Singlejunction1.at(is1).size(); is2++){
5332       HHparton endpoint = Singlejunction1.at(is1).at(is2).back();
5333 
5334       if(endpoint.col() != 0 && endpoint.acol() != 0 && ajunction){
5335         int loc = 0;
5336         HHparton tempparton1 = endpoint;
5337         if(tempparton1.id() == 21) {
5338           tempparton1.id(1);
5339           loc = findcloserepl(tempparton1,1, false, true, HH_showerptns, HH_thermal);
5340           tempparton1.id(21);
5341         }else{loc = findcloserepl(tempparton1,1, false, true, HH_showerptns, HH_thermal);}
5342         if(loc == 999999999 || loc > 0) {
5343           int fid = ((ran() > 0.33333333) ? ((ran() > 0.5) ? -1 : -2) : -3);
5344           HHparton fakep = tempparton1; fakep.id(fid); fakep.set_color(0);
5345           fakep.set_anti_color(endpoint.col());
5346           if(std::abs(fakep.id()) < 3) {
5347             fakep.mass(xmq);
5348           } else {fakep.mass(xms);}
5349           double fake_pT = (p_fake >= 1.) ? 0.282842712474619 : 0.; double fake_phi = 2. * 3.14159265358979 * ran();
5350           fakep.px(fake_pT * cos(fake_phi)); fakep.py(fake_pT * sin(fake_phi));
5351           if (number_p_fake == 0 || number_p_fake == 2){
5352             fakep.pz(-p_fake);
5353           } else if (number_p_fake == 1 || number_p_fake == 3) {
5354             fakep.pz(p_fake);
5355           } else {fakep.pz(0.);}
5356           number_p_fake++;
5357           fakep.e(std::sqrt(fakep.px()*fakep.px() + fakep.py()*fakep.py() + fakep.pz()*fakep.pz() + fakep.mass()*fakep.mass()));
5358           fakep.orig(-1); fakep.is_remnant(true);
5359           fakep.is_fakeparton(true);
5360           SP_remnants.add(fakep);
5361           Singlejunction1.at(is1).at(is2).push_back(fakep);
5362         }else if(loc < 0) {
5363           HH_thermal[-loc-1].acol(endpoint.col());
5364           HH_thermal[-loc-1].col(0);
5365           HH_thermal[-loc-1].is_used(true);
5366           HH_thermal[-loc-1].is_remnant(true); SP_remnants.add(HH_thermal[-loc-1]);
5367           SP_remnants[SP_remnants.num()-1].par(-loc-1);
5368           Singlejunction1.at(is1).at(is2).push_back(HH_thermal[-loc-1]);
5369         }
5370       }
5371     }
5372 
5373     for(int is3 = 0; is3 < Singlejunction1.at(is1).size(); is3++){
5374       HHparton endpoint = Singlejunction1.at(is1).at(is3).back();
5375 
5376       if(endpoint.col() != 0 && endpoint.acol() != 0 && !ajunction){
5377         int loc = 0;
5378         HHparton tempparton1 = endpoint;
5379         if(tempparton1.id() == 21) {
5380           tempparton1.id(-1);
5381           loc = findcloserepl(tempparton1,1, false, true, HH_showerptns, HH_thermal);
5382           tempparton1.id(21);
5383         }else{loc = findcloserepl(tempparton1,1, false, true, HH_showerptns, HH_thermal);}
5384         if(loc == 999999999 || loc > 0) {
5385           int fid = ((ran() > 0.33333333) ? ((ran() > 0.5) ? 1 : 2) : 3);
5386           HHparton fakep = tempparton1; fakep.id(fid); fakep.set_color(endpoint.acol());
5387           fakep.set_anti_color(0);
5388           if(std::abs(fakep.id()) < 3) {
5389             fakep.mass(xmq);
5390           } else {fakep.mass(xms);}
5391           double fake_pT = (p_fake >= 1.) ? 0.282842712474619 : 0.; double fake_phi = 2. * 3.14159265358979 * ran();
5392           fakep.px(fake_pT * cos(fake_phi)); fakep.py(fake_pT * sin(fake_phi));
5393           if (number_p_fake == 0 || number_p_fake == 2){
5394             fakep.pz(-p_fake);
5395           } else if (number_p_fake == 1 || number_p_fake == 3) {
5396             fakep.pz(p_fake);
5397           } else {fakep.pz(0.);}
5398           number_p_fake++;
5399           fakep.e(std::sqrt(fakep.px()*fakep.px() + fakep.py()*fakep.py() + fakep.pz()*fakep.pz() + fakep.mass()*fakep.mass()));
5400           fakep.orig(-1); fakep.is_remnant(true);
5401           fakep.is_fakeparton(true);
5402           SP_remnants.add(fakep);
5403           Singlejunction1.at(is1).at(is3).push_back(fakep);
5404         }else if(loc < 0) {
5405           HH_thermal[-loc-1].col(endpoint.acol());
5406           HH_thermal[-loc-1].acol(0);
5407           HH_thermal[-loc-1].is_used(true);
5408           HH_thermal[-loc-1].is_remnant(true); SP_remnants.add(HH_thermal[-loc-1]);
5409           SP_remnants[SP_remnants.num()-1].par(-loc-1);
5410           Singlejunction1.at(is1).at(is3).push_back(HH_thermal[-loc-1]);
5411         }
5412       }
5413     }
5414     ajunction = false; //resetting the variable.
5415   }
5416 
5417   //Working for Leg's in dijunction structure.
5418   for(int idj1 = 0; idj1 < Dijunction1.size(); idj1++){
5419     for(int idj2 = 0; idj2 < Dijunction1.at(idj1).size(); idj2++){
5420       HHparton endpoint = Dijunction1.at(idj1).at(idj2).back();
5421 
5422       if(DijunctionInfo1.at(idj1).at(idj2) == -1 && endpoint.col() != 0 && endpoint.acol() != 0){
5423         int loc = 0;
5424         HHparton tempparton1 = endpoint;
5425         if(tempparton1.id() == 21) {
5426           tempparton1.id(1);
5427           loc = findcloserepl(tempparton1,1, false, true, HH_showerptns, HH_thermal);
5428           tempparton1.id(21);
5429         }else{loc = findcloserepl(tempparton1,1, false, true, HH_showerptns, HH_thermal);}
5430         if(loc == 999999999 || loc > 0) {
5431           int fid = ((ran() > 0.33333333) ? ((ran() > 0.5) ? -1 : -2) : -3);
5432           HHparton fakep = tempparton1; fakep.id(fid); fakep.set_color(0);
5433           fakep.set_anti_color(endpoint.col());
5434           if(std::abs(fakep.id()) < 3) {
5435             fakep.mass(xmq);
5436           } else {fakep.mass(xms);}
5437           double fake_pT = (p_fake >= 1.) ? 0.282842712474619 : 0.; double fake_phi = 2. * 3.14159265358979 * ran();
5438           fakep.px(fake_pT * cos(fake_phi)); fakep.py(fake_pT * sin(fake_phi));
5439           if (number_p_fake == 0 || number_p_fake == 2){
5440             fakep.pz(-p_fake);
5441           } else if (number_p_fake == 1 || number_p_fake == 3) {
5442             fakep.pz(p_fake);
5443           } else {fakep.pz(0.);}
5444           number_p_fake++;
5445           fakep.e(std::sqrt(fakep.px()*fakep.px() + fakep.py()*fakep.py() + fakep.pz()*fakep.pz() + fakep.mass()*fakep.mass()));
5446           fakep.orig(-1); fakep.is_remnant(true);
5447           fakep.is_fakeparton(true);
5448           SP_remnants.add(fakep);
5449           Dijunction1.at(idj1).at(idj2).push_back(fakep);
5450         }else if(loc < 0) {
5451           HH_thermal[-loc-1].acol(endpoint.col());
5452           HH_thermal[-loc-1].col(0);
5453           HH_thermal[-loc-1].is_used(true);
5454           HH_thermal[-loc-1].is_remnant(true); SP_remnants.add(HH_thermal[-loc-1]);
5455           SP_remnants[SP_remnants.num()-1].par(-loc-1);
5456           Dijunction1.at(idj1).at(idj2).push_back(HH_thermal[-loc-1]);
5457         }
5458       }
5459     }
5460 
5461     for(int idj3 = 0; idj3 < Dijunction1.at(idj1).size(); idj3++){
5462       HHparton endpoint = Dijunction1.at(idj1).at(idj3).back();
5463 
5464       if(DijunctionInfo1.at(idj1).at(idj3) == 1 && endpoint.col() != 0 && endpoint.acol() != 0){
5465         int loc = 0;
5466         HHparton tempparton1 = endpoint;
5467         if(tempparton1.id() == 21) {
5468           tempparton1.id(-1);
5469           loc = findcloserepl(tempparton1,1, false, true, HH_showerptns, HH_thermal);
5470           tempparton1.id(21);
5471         }else{loc = findcloserepl(tempparton1,1, false, true, HH_showerptns, HH_thermal);}
5472         if(loc == 999999999 || loc > 0) {
5473           int fid = ((ran() > 0.33333333) ? ((ran() > 0.5) ? 1 : 2) : 3);
5474           HHparton fakep = tempparton1; fakep.id(fid); fakep.set_color(endpoint.acol());
5475           fakep.set_anti_color(0);
5476           if(std::abs(fakep.id()) < 3) {
5477             fakep.mass(xmq);
5478           } else {fakep.mass(xms);}
5479           double fake_pT = (p_fake >= 1.) ? 0.282842712474619 : 0.; double fake_phi = 2. * 3.14159265358979 * ran();
5480           fakep.px(fake_pT * cos(fake_phi)); fakep.py(fake_pT * sin(fake_phi));
5481           if (number_p_fake == 0 || number_p_fake == 2){
5482             fakep.pz(-p_fake);
5483           } else if (number_p_fake == 1 || number_p_fake == 3) {
5484             fakep.pz(p_fake);
5485           } else {fakep.pz(0.);}
5486           number_p_fake++;
5487           fakep.e(std::sqrt(fakep.px()*fakep.px() + fakep.py()*fakep.py() + fakep.pz()*fakep.pz() + fakep.mass()*fakep.mass()));
5488           fakep.orig(-1); fakep.is_remnant(true);
5489           fakep.is_fakeparton(true);
5490           SP_remnants.add(fakep);
5491           Dijunction1.at(idj1).at(idj3).push_back(fakep);
5492         }else if(loc < 0) {
5493           HH_thermal[-loc-1].col(endpoint.acol());
5494           HH_thermal[-loc-1].acol(0);
5495           HH_thermal[-loc-1].is_used(true);
5496           HH_thermal[-loc-1].is_remnant(true); SP_remnants.add(HH_thermal[-loc-1]);
5497           SP_remnants[SP_remnants.num()-1].par(-loc-1);
5498           Dijunction1.at(idj1).at(idj3).push_back(HH_thermal[-loc-1]);
5499         }
5500       }
5501     }
5502   }
5503 
5504   //since the repeating is needed for completing the junction structure, It is inevitable that there are repeated particle in Recombeary1, It's complicated to explain, and useless to focus on.
5505   // so that just delete repeated particles by check color Tags
5506   for(int irb1 = 0; irb1 < Recombearly1.size(); irb1++){ // pick one baryon
5507     for(int irb2 = 0; irb2 < Recombearly1.at(irb1).size(); irb2++){ // pick one particle in baryon
5508       for(int irb3 = irb2+1; irb3 < Recombearly1.at(irb1).size(); irb3++){ // checking through all particles in baryon
5509         if( (Recombearly1.at(irb1).at(irb2).col() == Recombearly1.at(irb1).at(irb3).col()) &&
5510           Recombearly1.at(irb1).at(irb2).acol() == Recombearly1.at(irb1).at(irb3).acol()){
5511           Recombearly1.at(irb1).erase(Recombearly1.at(irb1).begin()+irb3);
5512           irb3--;
5513         }
5514       }
5515     }
5516   }
5517 
5518   //dignositic measure{early recombined baryon}
5519   /*std::cout <<endl;
5520   std::cout <<" number of early recombined baryons : "<<Recombearly1.size()<<endl;
5521   for(int ibary1 = 0; ibary1 < Recombearly1.size(); ibary1++){
5522     std::cout <<"the "<< ibary1 <<" st baryon is made of ";
5523     for(int ibary2 = 0; ibary2 < Recombearly1.at(ibary1).size(); ibary2++){
5524       std::cout <<" { "<<Recombearly1.at(ibary1).at(ibary2).col()<<" , "<< Recombearly1.at(ibary1).at(ibary2).acol()<<" , "<< Recombearly1.at(ibary1).at(ibary2).id()<<" , "<< Recombearly1.at(ibary1).at(ibary2).e()  <<" } , ";
5525     }
5526     std::cout <<endl;
5527   }*/
5528 
5529   // force recombine baryons in Recombearly1
5530   for(int irb = 0; irb < Recombearly1.size(); irb++){
5531     double hbac2 = hbarc*hbarc;
5532 
5533     FourVector Pbaryon;
5534     Pbaryon.Set(
5535       Recombearly1.at(irb)[0].px()+Recombearly1.at(irb)[1].px()+Recombearly1.at(irb)[2].px(),
5536       Recombearly1.at(irb)[0].py()+Recombearly1.at(irb)[1].py()+Recombearly1.at(irb)[2].py(),
5537       Recombearly1.at(irb)[0].pz()+Recombearly1.at(irb)[1].pz()+Recombearly1.at(irb)[2].pz(),
5538       0.);
5539 
5540     //baryon(CM) velocity
5541     FourVector betaB; //really p[i]/e below
5542     betaB.Set(
5543       Pbaryon.x()/(Recombearly1.at(irb)[0].e()+Recombearly1.at(irb)[1].e()+Recombearly1.at(irb)[2].e()),
5544       Pbaryon.y()/(Recombearly1.at(irb)[0].e()+Recombearly1.at(irb)[1].e()+Recombearly1.at(irb)[2].e()),
5545       Pbaryon.z()/(Recombearly1.at(irb)[0].e()+Recombearly1.at(irb)[1].e()+Recombearly1.at(irb)[2].e()),
5546       0.);
5547     betaB.Set(
5548       betaB.x(),
5549       betaB.y(),
5550       betaB.z(),
5551       1./(sqrt(1. - (betaB.x()*betaB.x() + betaB.y()*betaB.y() + betaB.z()*betaB.z()))));
5552 
5553     //boosting into CM frame
5554     FourVector pos_BCM[3], p_BCM[3];
5555     pos_BCM[0] = Recombearly1.at(irb)[0].boost_pos(betaB);
5556     pos_BCM[1] = Recombearly1.at(irb)[1].boost_pos(betaB);
5557     pos_BCM[2] = Recombearly1.at(irb)[2].boost_pos(betaB);
5558     p_BCM[0] = Recombearly1.at(irb)[0].boost_P(betaB);
5559     p_BCM[1] = Recombearly1.at(irb)[1].boost_P(betaB);
5560     p_BCM[2] = Recombearly1.at(irb)[2].boost_P(betaB);
5561 
5562     //velocities in CM frame
5563     FourVector v_BCM[3];
5564     v_BCM[0].Set(p_BCM[0].x()/p_BCM[0].t(),p_BCM[0].y()/p_BCM[0].t(),p_BCM[0].z()/p_BCM[0].t(),0.); //these are really p[i]/e
5565     v_BCM[1].Set(p_BCM[1].x()/p_BCM[1].t(),p_BCM[1].y()/p_BCM[1].t(),p_BCM[1].z()/p_BCM[1].t(),0.);
5566     v_BCM[2].Set(p_BCM[2].x()/p_BCM[2].t(),p_BCM[2].y()/p_BCM[2].t(),p_BCM[2].z()/p_BCM[2].t(),0.);
5567 
5568     //propagating quarks until time of youngest quark
5569     double curtime = std::max(std::max(pos_BCM[0].t(), pos_BCM[1].t()), pos_BCM[2].t());
5570     FourVector cur_pos[3];
5571     cur_pos[0].Set(
5572       pos_BCM[0].x()+v_BCM[0].x()*(curtime-pos_BCM[0].t()),
5573       pos_BCM[0].y()+v_BCM[0].y()*(curtime-pos_BCM[0].t()),
5574       pos_BCM[0].z()+v_BCM[0].z()*(curtime-pos_BCM[0].t()),
5575       curtime);
5576     cur_pos[1].Set(
5577       pos_BCM[1].x()+v_BCM[1].x()*(curtime-pos_BCM[1].t()),
5578       pos_BCM[1].y()+v_BCM[1].y()*(curtime-pos_BCM[1].t()),
5579       pos_BCM[1].z()+v_BCM[1].z()*(curtime-pos_BCM[1].t()),
5580       curtime);
5581     cur_pos[2].Set(
5582       pos_BCM[2].x()+v_BCM[2].x()*(curtime-pos_BCM[2].t()),
5583       pos_BCM[2].y()+v_BCM[2].y()*(curtime-pos_BCM[2].t()),
5584       pos_BCM[2].z()+v_BCM[2].z()*(curtime-pos_BCM[2].t()),
5585       curtime);
5586 
5587     //finding position of CM at curtime
5588     FourVector pos_CM;
5589     pos_CM.Set(
5590       (cur_pos[0].x()*Recombearly1.at(irb)[0].mass()+cur_pos[1].x()*Recombearly1.at(irb)[1].mass()+cur_pos[2].x()*Recombearly1.at(irb)[2].mass())/(Recombearly1.at(irb)[0].mass()+Recombearly1.at(irb)[1].mass()+Recombearly1.at(irb)[2].mass()),
5591       (cur_pos[0].y()*Recombearly1.at(irb)[0].mass()+cur_pos[1].y()*Recombearly1.at(irb)[1].mass()+cur_pos[2].y()*Recombearly1.at(irb)[2].mass())/(Recombearly1.at(irb)[0].mass()+Recombearly1.at(irb)[1].mass()+Recombearly1.at(irb)[2].mass()),
5592       (cur_pos[0].z()*Recombearly1.at(irb)[0].mass()+cur_pos[1].z()*Recombearly1.at(irb)[1].mass()+cur_pos[2].z()*Recombearly1.at(irb)[2].mass())/(Recombearly1.at(irb)[0].mass()+Recombearly1.at(irb)[1].mass()+Recombearly1.at(irb)[2].mass()),
5593       curtime);
5594 
5595     //finding position of baryon in lab frame
5596     betaB.Set(-betaB.x(),-betaB.y(),-betaB.z(),betaB.t());
5597     FourVector pos_lab = HHboost(betaB, pos_CM);
5598 
5599     //finding relative positions of partons in CM frame
5600     FourVector pos_rel_square[2];
5601     pos_rel_square[0].Set(
5602       (cur_pos[0].x()-cur_pos[1].x())/sqrt(2.),
5603       (cur_pos[0].y()-cur_pos[1].y())/sqrt(2.),
5604       (cur_pos[0].z()-cur_pos[1].z())/sqrt(2.),
5605       0.);
5606     pos_rel_square[1].Set(
5607       ((cur_pos[0].x()*Recombearly1.at(irb)[0].mass()+cur_pos[1].x()*Recombearly1.at(irb)[1].mass())/(Recombearly1.at(irb)[0].mass()+Recombearly1.at(irb)[1].mass())-cur_pos[2].x())*sqrt(2./3.),
5608       ((cur_pos[0].y()*Recombearly1.at(irb)[0].mass()+cur_pos[1].y()*Recombearly1.at(irb)[1].mass())/(Recombearly1.at(irb)[0].mass()+Recombearly1.at(irb)[1].mass())-cur_pos[2].y())*sqrt(2./3.),
5609       ((cur_pos[0].z()*Recombearly1.at(irb)[0].mass()+cur_pos[1].z()*Recombearly1.at(irb)[1].mass())/(Recombearly1.at(irb)[0].mass()+Recombearly1.at(irb)[1].mass())-cur_pos[2].z())*sqrt(2./3.),
5610       0.);
5611 
5612     //so far, values to form a baryon are set, now make hadron objects based on this information
5613     //now we're forming the hadron
5614     HHhadron formedhadron;
5615     //setting the hadron values: is a recombined hadron, mass, and parents
5616     formedhadron.is_recohad(true);
5617     formedhadron.mass( p_BCM[0].t() + p_BCM[1].t() + p_BCM[2].t() );
5618 
5619     //setting hadron position and momentum vectors
5620     Pbaryon.Set(
5621       Pbaryon.x(),
5622       Pbaryon.y(),
5623       Pbaryon.z(),
5624       sqrt(Pbaryon.x()*Pbaryon.x() + Pbaryon.y()*Pbaryon.y() + Pbaryon.z()*Pbaryon.z() + formedhadron.mass()*formedhadron.mass()));
5625     formedhadron.pos(pos_lab);
5626     formedhadron.P(Pbaryon);
5627 
5628     //need to choose *what* hadron we've formed... base this on the parton id's, mass, & if excited
5629     //might want to do this differently? void f'n(partoncollection, formedhadron)?
5630     //since set_baryon_id function works with object of parton_colection class, make temporary parton_collection
5631     parton_collection tempobject; //since the generator resets all components, don't need to reset the vactors in it
5632     tempobject.add(Recombearly1.at(irb)[0]);
5633     tempobject.add(Recombearly1.at(irb)[1]);
5634     tempobject.add(Recombearly1.at(irb)[2]);
5635 
5636     set_baryon_id(tempobject, formedhadron);
5637 
5638     formedhadron.is_shth(thermal_parton_junction[irb]);
5639 
5640     //need to add the hadron to the collection
5641     HH_hadrons.add(formedhadron);
5642   }
5643 
5644   //from now we need re indexing a of the particles in SP_remnants by comparing color tag in Juncstructure component.
5645   //Maybe there would not be a problem in the used_junction value, but take most defensive measure for the possible error.
5646   std::vector<int> checking;
5647   bool indicecheck = false;
5648   for (int irem = 0; irem < SP_remnants.num(); irem++){
5649     for(int ijs1 = 0; ijs1 < JuncStructure.size(); ijs1++){
5650       for(int ijs2 = 0; ijs2 < JuncStructure.at(ijs1).size(); ijs2++){
5651         for(int ijs3 = 0; ijs3 < JuncStructure.at(ijs1).at(ijs2).size(); ijs3++){
5652           if( (SP_remnants[irem].col() == JuncStructure.at(ijs1).at(ijs2).at(ijs3).col()) &&
5653             (SP_remnants[irem].acol() == JuncStructure.at(ijs1).at(ijs2).at(ijs3).acol()) ){
5654             SP_remnants[irem].used_junction(true);
5655             checking.push_back(irem);
5656           }
5657         }
5658       }
5659     }
5660   }
5661   for (int irem = 0; irem < SP_remnants.num(); irem++){
5662     for(int icheck = 0; icheck < checking.size(); icheck++){
5663       if(irem == checking.at(icheck)){ indicecheck = true; }
5664     }
5665     if(indicecheck = false){
5666       SP_remnants[irem].used_junction(false);
5667     }
5668   }
5669   // Now set up for junction is done, let's check the left partons to establish string structure
5670 
5671 
5672   //std::cout <<endl<<"let's check left particles!"<<endl;
5673   /*for(int irp = 0 ; irp < SP_remnants.num(); irp++) {
5674     if(SP_remnants[irp].used_junction() == false){
5675       std::cout << "( "<<SP_remnants[irp].id()<<" , "<<SP_remnants[irp].col()<<" , "<<SP_remnants[irp].acol()<<" ) "<<endl;
5676     }
5677   }*/
5678 
5679   for(int ileft = 0; ileft < SP_remnants.num(); ileft++){
5680     if(SP_remnants[ileft].used_junction() == false){
5681       finalstring.push_back(SP_remnants[ileft]);
5682     }
5683   }
5684 
5685   // contains the chopped off legs of junctions
5686   for(int itail1 = 0; itail1 < Tailoredstring1.size(); itail1++ ){
5687     for(int itail2 = 0; itail2 < Tailoredstring1.at(itail1).size(); itail2++){
5688       finalstring.push_back(Tailoredstring1.at(itail1).at(itail2));
5689     }
5690   }
5691 
5692   //std::cout <<endl<<"check final particles!"<<endl;
5693   /*for(int ifin = 0; ifin < finalstring.size(); ifin++){
5694     std::cout << finalstring.at(ifin).id() << "," << finalstring.at(ifin).col() << "," << finalstring.at(ifin).acol() <<endl;
5695   }*/
5696 
5697   /*std::cout <<endl<<"check final particles!"<<endl;
5698   for(int ifin = 0; ifin < finalstring.size(); ifin++){
5699     std::cout <<" { "<< finalstring.at(ifin).col() << " , " << finalstring.at(ifin).acol() << " } "<<endl;
5700   }*/
5701 
5702   //so far, particles in finalstring are ready for being transfered into PYTHIA, since we don't need to set mother, daughter tag.
5703   //but, still need to care about single junction and dijunction system, especially for the mother daughter tag!
5704   // mother, daughter tags are working with the execution order{= order of being declared in pythia} so before tossing the datum to PYTHIA, rearrange order in the vector
5705   // declare the transit space for these particles, while moving onto vector to vector, partons are assigned mother, daughter tag tor PYTHIA running{definition of that tags are given well in main21.cc file in   /installed pythia folder/bin/example/ }
5706   vector<vector<HHparton>> Transitdijunction1;
5707   vector<HHparton> Transitdijunction2; // two fake mother B, B-bar and fake q,qbar added and give mother daughter tags!
5708   vector<vector<vector<HHparton>>> Tempsorting1; // vectors for rearranging legs in dijunction{Desired arrangement : identity 1, 1, 0 , -1, -1}
5709   vector<vector<HHparton>> Tempsorting2;
5710   vector<vector<HHparton>> Transitsinglejunction1;
5711   vector<HHparton> Transitsinglejunction2;
5712   vector<HHparton> WaitingLineforPY; // final list of partons with complete M,D tag and col tags
5713 
5714   //set the value for incrementation in mother daughter tag.
5715   //and start from dijunction, first, check the identity{1: junction leg, -1: anti_junction leg, 0:shared leg}, since we'll read col tag first, consider identity=1 leg first and then 0, -1
5716   for(int dijuncfin1 = 0; dijuncfin1 < Dijunction1.size(); dijuncfin1++){ // Going to find shared leg and attach fake partons to the begin and the end of the leg
5717     for(int dijuncfin2= 0; dijuncfin2 < 5; dijuncfin2++){ //inspect through five legs
5718       if(DijunctionInfo1.at(dijuncfin1).at(dijuncfin2) == 0){ //check whether it's shared leg{identity =0} and add fakepartons to the first and second posittion in the vector
5719         HHparton fakeq;
5720         HHparton fakeqbar;
5721         fakeq.id(1); fakeq.set_color(Dijunction1.at(dijuncfin1).at(dijuncfin2).at(0).col());
5722         fakeq.PY_stat(-21); fakeq.mass(xmq); fakeq.e(xmq); fakeq.orig(-1);
5723         fakeq.px(0.); fakeq.py(0.); fakeq.pz(0.);
5724         int endpoint = Dijunction1.at(dijuncfin1).at(dijuncfin2).size() - 1;
5725         fakeqbar.id(-1); fakeqbar.set_anti_color(Dijunction1.at(dijuncfin1).at(dijuncfin2).at(endpoint).acol());
5726         fakeqbar.PY_stat(-21); fakeqbar.mass(xmq); fakeqbar.e(xmq); fakeqbar.orig(-1);
5727         fakeqbar.px(0.); fakeqbar.py(0.); fakeqbar.pz(0.);
5728         std::vector<HHparton>::iterator it2 = Dijunction1.at(dijuncfin1).at(dijuncfin2).begin();
5729         Dijunction1.at(dijuncfin1).at(dijuncfin2).insert(it2, fakeqbar);
5730         std::vector<HHparton>::iterator it1 = Dijunction1.at(dijuncfin1).at(dijuncfin2).begin();
5731         Dijunction1.at(dijuncfin1).at(dijuncfin2).insert(it1, fakeq);
5732       }
5733     }
5734     for(int isort1 = 0; isort1 < 5; isort1++){
5735       if(DijunctionInfo1.at(dijuncfin1).at(isort1) == 1){
5736         Tempsorting2.push_back(Dijunction1.at(dijuncfin1).at(isort1));
5737       }
5738     }
5739     for(int isort1 = 0; isort1 < 5; isort1++){
5740       if(DijunctionInfo1.at(dijuncfin1).at(isort1) == 0){
5741         Tempsorting2.push_back(Dijunction1.at(dijuncfin1).at(isort1));
5742       }
5743     }
5744     for(int isort1 = 0; isort1 < 5; isort1++){
5745       if(DijunctionInfo1.at(dijuncfin1).at(isort1) == -1){
5746         Tempsorting2.push_back(Dijunction1.at(dijuncfin1).at(isort1));
5747       }
5748     }
5749     Tempsorting1.push_back(Tempsorting2);
5750     Tempsorting2.clear();
5751   } //first looping to add fake partons is Finished, now sort the order of the legs to be identity 1,1,0,-1,-1
5752 
5753   //dignostic measure{Dijunction1}
5754   /*std::cout <<endl;
5755   std::cout <<" List of Dijunction Structure"<<endl;
5756   for(int icheck1 = 0; icheck1 < Dijunction1.size(); icheck1++){
5757     std::cout <<" Dijunction : "<<icheck1<<endl;
5758     for(int icheck2 = 0 ; icheck2 < Dijunction1.at(icheck1).size(); icheck2++){
5759       std::cout <<" Leg "<<icheck2<<" : "<<"{ identity : "<< DijunctionInfo1.at(icheck1).at(icheck2)<<" }  ";
5760       for(int icheck3 = 0; icheck3 < Dijunction1.at(icheck1).at(icheck2).size(); icheck3++){
5761         std::cout <<" ( "<<Dijunction1.at(icheck1).at(icheck2).at(icheck3).col()<<" , "<<Dijunction1.at(icheck1).at(icheck2).at(icheck3).acol()<< " )  ";
5762       }
5763       std::cout <<endl;
5764     }
5765   }*/
5766 
5767   //dignostic measure{Tempsorting}
5768   /*std::cout <<endl;
5769   std::cout <<" List of Dijunction Structure"<<endl;
5770   for(int icheck1 = 0; icheck1 < Tempsorting1.size(); icheck1++){
5771     std::cout <<" Tempsorted Dijunction1 : "<<icheck1<<endl;
5772     for(int icheck2 = 0 ; icheck2 < Tempsorting1.at(icheck1).size(); icheck2++){
5773       for(int icheck3 = 0; icheck3 < Tempsorting1.at(icheck1).at(icheck2).size(); icheck3++){
5774         std::cout <<" ( "<<Tempsorting1.at(icheck1).at(icheck2).at(icheck3).col()<<" , "<<Tempsorting1.at(icheck1).at(icheck2).at(icheck3).acol()<< " )  "<<" , "<<Tempsorting1.at(icheck1).at(icheck2).at(icheck3).x_t();
5775       }
5776       std::cout <<endl;
5777     }
5778   }*/
5779 
5780   // adding fake partons and sorting them with right order{Junctionleg1,2 shared leg, antijunctionleg1,2} is finished so far, Now form a fake mothers to prepare for PYTHIA
5781   for(int itag1 = 0; itag1 < Tempsorting1.size(); itag1++){ /// we need to link Tempsorting1 with Transitdijunction1,
5782     //First, put fake B,Bbar into 1st and 2nd position of Transitdijunction2
5783     parton_collection FakeBaryonElements; // array of quarks in fake B
5784     parton_collection FakeAntibaryonElements; // array of anti quarks in fake Bbar
5785 
5786     FakeBaryonElements.add(Tempsorting1.at(itag1).at(0).back()); // quarks to form fake FakeBaryon
5787     FakeBaryonElements.add(Tempsorting1.at(itag1).at(1).back());
5788     FakeBaryonElements.add(Tempsorting1.at(itag1).at(2).at(0));
5789     // for the corrspondence with pdg particle id, sorting the these ids based on absolute value.
5790 
5791     for(int iswap = 0; iswap < 3; iswap++){
5792       if(abs(FakeBaryonElements[2].id()) > abs(FakeBaryonElements[1].id())){ std::swap(FakeBaryonElements[2], FakeBaryonElements[1]) ; }
5793       if(abs(FakeBaryonElements[1].id()) > abs(FakeBaryonElements[0].id())){ std::swap(FakeBaryonElements[1], FakeBaryonElements[0]) ; }
5794       if(abs(FakeBaryonElements[2].id()) > abs(FakeBaryonElements[0].id())){ std::swap(FakeBaryonElements[2], FakeBaryonElements[0]) ; }
5795     }
5796 
5797     FakeAntibaryonElements.add(Tempsorting1.at(itag1).at(2).at(1)); //anti quarks to form FakeAntiBaryon
5798     FakeAntibaryonElements.add(Tempsorting1.at(itag1).at(3).back());
5799     FakeAntibaryonElements.add(Tempsorting1.at(itag1).at(4).back());
5800 
5801     for(int iswap = 0; iswap < 3; iswap++){
5802       if(abs(FakeAntibaryonElements[2].id()) > abs(FakeAntibaryonElements[1].id())){ std::swap(FakeAntibaryonElements[2], FakeAntibaryonElements[1]) ; }
5803       if(abs(FakeAntibaryonElements[1].id()) > abs(FakeAntibaryonElements[0].id())){ std::swap(FakeAntibaryonElements[1], FakeAntibaryonElements[0]) ; }
5804       if(abs(FakeAntibaryonElements[2].id()) > abs(FakeAntibaryonElements[0].id())){ std::swap(FakeAntibaryonElements[2], FakeAntibaryonElements[0]) ; }
5805     }
5806 
5807     HHhadron store_id_hadron1;
5808     set_baryon_id(FakeBaryonElements, store_id_hadron1);
5809     HHhadron store_id_hadron2;
5810     set_baryon_id(FakeAntibaryonElements, store_id_hadron2);
5811 
5812     FakeBaryonElements.clear();
5813     FakeAntibaryonElements.clear();
5814 
5815     HHparton fakeB;
5816     HHparton fakeBbar;
5817     fakeB.id(store_id_hadron1.id());
5818     fakeB.PY_stat(-11);
5819     fakeB.mass(3*xmq);
5820     fakeB.e(3*xmq);
5821     fakeB.px(0.);
5822     fakeB.py(0.);
5823     fakeB.pz(0.);
5824 
5825     fakeBbar.id(store_id_hadron2.id());
5826     fakeBbar.PY_stat(-11);
5827     fakeBbar.mass(3*xmq);
5828     fakeBbar.e(3*xmq);
5829     fakeBbar.px(0.);
5830     fakeBbar.py(0.);
5831     fakeBbar.pz(0.);
5832 
5833     fakeB.PY_tag1(Tempsorting1.at(itag1).at(0).back().col());
5834       fakeB.PY_tag2(Tempsorting1.at(itag1).at(1).back().col());
5835       fakeB.PY_tag3(Tempsorting1.at(itag1).at(2).at(0).col());
5836 
5837     fakeBbar.PY_tag1(Tempsorting1.at(itag1).at(2).at(1).acol());
5838       fakeBbar.PY_tag2(Tempsorting1.at(itag1).at(3).back().acol());
5839       fakeBbar.PY_tag3(Tempsorting1.at(itag1).at(4).back().acol());
5840 
5841     //so far, we formed two fake partons, which would be at the center of Junction and Antijunction, Now put them 0th and 1st position of Transirdijunction1 vector
5842     Transitdijunction2.push_back(fakeB);
5843     Transitdijunction2.push_back(fakeBbar);
5844     Transitdijunction1.push_back(Transitdijunction2);
5845     Transitdijunction2.clear();
5846   }
5847 
5848   //the next step is to set M,D Tags
5849   int Intag = 0; // tag for internal M,D tagging process
5850   for(int iMD1 = 0; iMD1 < Tempsorting1.size(); iMD1++){ //after working in these Legs, we will return the partons to Transitdijunction1,
5851     // so far, the order in the vectors{Dijunction1, DijunctionInfo1, Tempsorting, Transitdijunction1} are unified, but the difference is the value in each vectors
5852     vector<HHparton> Leg1 = Tempsorting1.at(iMD1).at(0); // for convenience, reassigning legs in sorted dijunction structure.{identity 1,1,0,-1,-1}
5853     vector<HHparton> Leg2 = Tempsorting1.at(iMD1).at(1);
5854     vector<HHparton> Leg3 = Tempsorting1.at(iMD1).at(2);
5855     vector<HHparton> Leg4 = Tempsorting1.at(iMD1).at(3);
5856     vector<HHparton> Leg5 = Tempsorting1.at(iMD1).at(4);
5857     //starting from Leg1{identity1}
5858     for(int ileg1 = 0; ileg1 < Leg1.size(); ileg1++){
5859       Leg1.at(ileg1).PY_par1(0);  // the mother of first leg1, 2 should be first fakebaryon{located 1st in the Transitdijunction2 vector!}
5860       Leg1.at(ileg1).PY_par2(0);
5861       Transitdijunction1.at(iMD1).push_back(Leg1.at(ileg1)); //toss Leg1 to the Transirdijunction1.at{iMD}, which would be the last step before WaitingLineforPY
5862     }
5863     for(int ileg2 = 0; ileg2 < Leg2.size(); ileg2++){
5864       Leg2.at(ileg2).PY_par1(0); // the mother of first leg1, 2 should be first fakebaryon{located 1st in the Transitdijunction2 vector!}
5865       Leg2.at(ileg2).PY_par2(0);
5866       Transitdijunction1.at(iMD1).push_back(Leg2.at(ileg2));
5867     }
5868     //for leg3, because of first and end fake particles, it goes differently from other legs
5869     Intag = 2 + Leg1.size() + Leg2.size(); // Previous tag + two fakemothers + Leg1 + Leg2
5870     //First of all, fake parton pairs are located for the convenience of MD tagging
5871     Leg3.at(0).PY_par1(0);//daughter of fakeB
5872     Leg3.at(0).PY_par2(0);
5873     Leg3.at(0).PY_dau1(Intag + Leg4.size() + Leg5.size() + 2); // daughter tags for gluons between two fake qqbar
5874     Leg3.at(0).PY_dau2(Intag + Leg4.size() + Leg5.size() + Leg3.size()- 1); // since
5875     Leg3.at(1).PY_par1(1);//daughter of fakeBbar
5876     Leg3.at(1).PY_par2(1);
5877     Leg3.at(1).PY_dau1(Intag + Leg4.size() + Leg5.size() + 2);
5878     Leg3.at(1).PY_dau2(Intag + Leg4.size() + Leg5.size() + Leg3.size()- 1);
5879 
5880     Transitdijunction1.at(iMD1).push_back(Leg3.at(0));
5881     Transitdijunction1.at(iMD1).push_back(Leg3.at(1)); // push first two fake partons and append remnants at the last, this is for convenience
5882 
5883     Transitdijunction1.at(iMD1).at(0).PY_dau1(2); // correcting daughter tags of fake B located at 0
5884     Transitdijunction1.at(iMD1).at(0).PY_dau2(Intag);
5885     Transitdijunction1.at(iMD1).at(1).PY_dau1(Intag + 1); //setting starting daughter tag of fakeBbar located at 1
5886     Transitdijunction1.at(iMD1).at(1).PY_dau2(Intag + 1 + Leg4.size() + Leg5.size() );
5887 
5888     for(int ileg4 = 0 ; ileg4 < Leg4.size(); ileg4++){
5889       Leg4.at(ileg4).PY_par1(1);
5890       Leg4.at(ileg4).PY_par2(1);
5891       Transitdijunction1.at(iMD1).push_back(Leg4.at(ileg4));
5892     }
5893     for(int ileg5 = 0 ; ileg5 < Leg5.size(); ileg5++){
5894       Leg5.at(ileg5).PY_par1(1);
5895       Leg5.at(ileg5).PY_par2(1);
5896       Transitdijunction1.at(iMD1).push_back(Leg5.at(ileg5));
5897     }
5898     for(int ileg3 = 2; ileg3 < Leg3.size(); ileg3++){ // mother tags for the gluons between two fake qqbar pair
5899       Leg3.at(ileg3).PY_par1(Intag);
5900       Leg3.at(ileg3).PY_par2(Intag + 1);
5901       Transitdijunction1.at(iMD1).push_back(Leg3.at(ileg3));
5902     }
5903   } // Inner tagging loop is finished for dijunction system,{That is, Information in Tempsorting1 is transfered to Transitdijunction1}
5904 
5905   //dignostic measure{Transitdijunction1}
5906   /*std::cout <<endl<< " the order of data is eNum >> id >> stat >> par1 >> par2 >> dau1 >> dau2 "<< endl;
5907   for(int icheck1 = 0; icheck1 <  Transitdijunction1.size(); icheck1++ ){
5908     for(int i = 0; i <  Transitdijunction1.at(icheck1).size(); i++){
5909       vector<HHparton> temp = Transitdijunction1.at(icheck1);
5910       std::cout  << i <<"   "<< temp.at(i).id() <<"   "<< temp.at(i).PY_stat() <<"   "<< temp.at(i).PY_par1() <<"   "<< temp.at(i).PY_par2() <<"   "
5911       << temp.at(i).PY_dau1() <<"   "<< temp.at(i).PY_dau2() << "  ( "<<  temp.at(i).col()<< " , " << temp.at(i).acol() << " ) " <<endl;
5912     }
5913   }*/
5914 
5915   //Now,start working on Single Junction System.
5916   for(int iSJ = 0; iSJ < Singlejunction1.size(); iSJ++){ // this process is for trasferring information from Singlejunction1 into Transitsinglejunction1, and finally they will be located at WaitingLineforPY
5917     //based on the partons at the end of each Leg, add fake mother baryon first.
5918     parton_collection FakeBaryonElements; // array of quarks in fake mother
5919 
5920     HHparton q1 = Singlejunction1.at(iSJ).at(0).back();
5921     HHparton q2 = Singlejunction1.at(iSJ).at(1).back();
5922     HHparton q3 = Singlejunction1.at(iSJ).at(2).back();
5923 
5924     HHparton q1fin = q1;
5925     HHparton q2fin = q2;
5926     HHparton q3fin = q3;
5927 
5928     FakeBaryonElements.add(q1fin); //add first particle in 1st leg in iSJ_st singlejunction
5929     FakeBaryonElements.add(q2fin); //add first particle in 2nd leg in iSJ_st singlejunction
5930     FakeBaryonElements.add(q3fin); //add first particle in 3rd leg in iSJ_st singlejunction
5931 
5932     // for the corrspondence with pdg particle id, sorting the these ids based on absolute value
5933     for(int iswap = 0; iswap < 3; iswap++){
5934       if(abs(FakeBaryonElements[2].id()) > abs(FakeBaryonElements[1].id())){ std::swap(FakeBaryonElements[2], FakeBaryonElements[1]) ; }
5935       if(abs(FakeBaryonElements[1].id()) > abs(FakeBaryonElements[0].id())){ std::swap(FakeBaryonElements[1], FakeBaryonElements[0]) ; }
5936       if(abs(FakeBaryonElements[2].id()) > abs(FakeBaryonElements[0].id())){ std::swap(FakeBaryonElements[2], FakeBaryonElements[0]) ; }
5937     }
5938 
5939     HHhadron store_id_hadron1;
5940     set_baryon_id(FakeBaryonElements, store_id_hadron1);
5941 
5942     int m_id = store_id_hadron1.id();
5943     if((q1.id() < 0 && m_id > 0) || (q1.id() > 0 && m_id < 0)){
5944       m_id *= -1;
5945     }
5946 
5947     HHparton fakeB;
5948     fakeB.id(m_id); fakeB.PY_stat(-11); fakeB.mass(3*xmq); fakeB.e(3*xmq);
5949     fakeB.px(0.); fakeB.py(0.); fakeB.pz(0.);
5950     if(q1.id() > 0){fakeB.PY_tag1(q1.col()); fakeB.PY_tag2(q2.col()); fakeB.PY_tag3(q3.col());}
5951     else{fakeB.PY_tag1(q1.acol()); fakeB.PY_tag2(q2.acol()); fakeB.PY_tag3(q3.acol());}
5952     Transitsinglejunction2.push_back(fakeB);
5953     Transitsinglejunction1.push_back(Transitsinglejunction2);
5954     Transitsinglejunction2.clear();
5955   } // so farfake mother is added to all single junction vectors{vectors of partons}, so we need to remember all execution number is incremented by one because of this fake baryons
5956 
5957   for(int iSJ = 0; iSJ < Singlejunction1.size(); iSJ++){
5958     vector<HHparton> Leg1 = Singlejunction1.at(iSJ).at(0);
5959     vector<HHparton> Leg2 = Singlejunction1.at(iSJ).at(1);
5960     vector<HHparton> Leg3 = Singlejunction1.at(iSJ).at(2);
5961 
5962     for(int ileg1 = 0; ileg1 < Leg1.size(); ileg1++ ){
5963       Leg1.at(ileg1).PY_par1(0); // setting the mother tag as zero, which indicates the first particle in the Transit
5964       Leg1.at(ileg1).PY_par2(0);
5965       Transitsinglejunction1.at(iSJ).push_back(Leg1.at(ileg1));
5966     }
5967     for(int ileg2 = 0; ileg2 < Leg2.size(); ileg2++ ){
5968       Leg2.at(ileg2).PY_par1(0); // setting the mother tag as zero, which indicates the first particle in the Transit
5969       Leg2.at(ileg2).PY_par2(0);
5970       Transitsinglejunction1.at(iSJ).push_back(Leg2.at(ileg2));
5971     }
5972     for(int ileg3 = 0; ileg3 < Leg3.size(); ileg3++ ){
5973       Leg3.at(ileg3).PY_par1(0); // setting the mother tag as zero, which indicates the first particle in the Transit
5974       Leg3.at(ileg3).PY_par2(0);
5975       Transitsinglejunction1.at(iSJ).push_back(Leg3.at(ileg3));
5976     }
5977     Transitsinglejunction1.at(iSJ).at(0).PY_dau1(1);//dau tag starting from 1 {after zero, which means fake mother baryon}
5978     Transitsinglejunction1.at(iSJ).at(0).PY_dau2(Leg1.size() + Leg2.size() + Leg3.size());//dau tag starting from 1 {after zero, which means fake mother baryon}
5979   }// At last, iSJ_st Singlejunction1 partons are moved to  iSJ_st vector component in Transitsinglejunction1
5980 
5981   //dignostic measure{Transitsinglejunction1}
5982   /*std::cout <<endl<< " the order of data is eNum >> id >> stat >> par1 >> par2 >> dau1 >> dau2 "<< endl;
5983   for(int icheck1 = 0; icheck1 <  Transitsinglejunction1.size(); icheck1++ ){
5984     std::cout <<endl<<"SingleJunction : "<<icheck1<<endl;
5985     for(int i = 0; i <  Transitsinglejunction1.at(icheck1).size(); i++){
5986       vector<HHparton> temp = Transitsinglejunction1.at(icheck1);
5987       std::cout  << i <<"   "<< temp.at(i).id() <<"   "<< temp.at(i).PY_stat() <<"   "<< temp.at(i).PY_par1() <<"   "<< temp.at(i).PY_par2() <<"   "
5988       << temp.at(i).PY_dau1() <<"   "<< temp.at(i).PY_dau2() << "  ( "<<  temp.at(i).col()<< " , " << temp.at(i).acol() << " ) " <<endl;
5989     }
5990   }*/
5991 
5992   //dignostic measure{Dijunction1}
5993   /*std::cout <<endl;
5994   std::cout <<" List of Tempsorting for Dijunction"<<endl;
5995   for(int icheck1 = 0; icheck1 < Tempsorting1.size(); icheck1++){
5996     std::cout <<" Sorted Leg : "<<icheck1<<endl;
5997     for(int icheck2 = 0 ; icheck2 < Tempsorting1.at(icheck1).size(); icheck2++){
5998         std::cout <<" ( "<<Tempsorting1.at(icheck1).at(icheck2).col()<<" , "<<Tempsorting1.at(icheck1).at(icheck2).acol()<< " )  ";
5999     }
6000     std::cout <<endl;
6001   }*/
6002 
6003   //So far, M,D tags for each junction and dijunction structure are designated. and EP_conservation checking will be done through Transitdijunction1 and Transitsinglejunction1 vectors
6004   for(int itd1 = 0; itd1 < Transitdijunction1.size(); itd1++){
6005     /*JSINFO << "This is dijunction " << itd1+1 << " before:";
6006     for(int i = 0; i <  Transitdijunction1.at(itd1).size(); i++){
6007       vector<HHparton> temp = Transitdijunction1.at(itd1);
6008       std::cout  << i <<"   "<< temp.at(i).id() <<"   "<< temp.at(i).PY_stat() <<"   "<< temp.at(i).PY_par1() <<"   "<< temp.at(i).PY_par2() <<"   "
6009       << temp.at(i).PY_dau1() <<"   "<< temp.at(i).PY_dau2() << "  ( "<<  temp.at(i).col()<< " , " << temp.at(i).acol() << " ) "
6010       << "  ( "<<  temp.at(i).e()<< " , " << temp.at(i).px()<< " , " << temp.at(i).py()<< " , " << temp.at(i).pz() << " ) "
6011       << "  ( "<<  temp.at(i).t()<< " , " << temp.at(i).x()<< " , " << temp.at(i).y()<< " , " << temp.at(i).z() << " ) " << std::endl;
6012     }*/
6013     bool EP_conserved = false;
6014     while(!EP_conserved){
6015       EP_conserved = true;
6016       for(int i=0; i<Transitdijunction1.at(itd1).size(); ++i){
6017         if(Transitdijunction1[itd1][i].PY_stat() >= 0 && std::abs(Transitdijunction1[itd1][i].id()) < 1000){
6018           continue;
6019         }
6020         FourVector P_new(0.,0.,0.,0.);
6021         FourVector pos_new(0.,0.,0.,0.);
6022         int jmax = (Transitdijunction1[itd1][i].PY_dau2() > Transitdijunction1[itd1][i].PY_dau1()) ? Transitdijunction1[itd1][i].PY_dau2() : Transitdijunction1[itd1][i].PY_dau1();
6023         //JSINFO << "jmax = " << jmax;
6024         for(int j=Transitdijunction1[itd1][i].PY_dau1(); j<jmax+1; ++j){
6025           double n = double(j-Transitdijunction1[itd1][i].PY_dau1())+1.;
6026           //JSINFO << "n = " << n;
6027           //JSINFO << "transdijunct.x_t = "<<Transitdijunction1[itd1][j].x_t();
6028           //JSINFO << pos_new.t()+(Transitdijunction1[itd1][j].x_t()-pos_new.t())/n;
6029           P_new.Set(
6030             P_new.x()+Transitdijunction1[itd1][j].px(),
6031             P_new.y()+Transitdijunction1[itd1][j].py(),
6032             P_new.z()+Transitdijunction1[itd1][j].pz(),
6033             P_new.t()+Transitdijunction1[itd1][j].e());
6034           pos_new.Set(
6035             pos_new.x()+(Transitdijunction1[itd1][j].x()-pos_new.x())/n,
6036             pos_new.y()+(Transitdijunction1[itd1][j].y()-pos_new.y())/n,
6037             pos_new.z()+(Transitdijunction1[itd1][j].z()-pos_new.z())/n,
6038             pos_new.t()+(Transitdijunction1[itd1][j].x_t()-pos_new.t())/n);
6039         }
6040         //JSINFO << "p = (" << P_new.t() << ", " << P_new.y() << ", " << P_new.y() << ", " << P_new.z() << ")";
6041         //JSINFO << "x = (" << pos_new.t() << ", " << pos_new.y() << ", " << pos_new.y() << ", " << pos_new.z() << ")";
6042         if((dif2(P_new,Transitdijunction1[itd1][i].P())+(P_new.t()-Transitdijunction1[itd1][i].e())*(P_new.t()-Transitdijunction1[itd1][i].e()) > 0.00000001/*0.0001^2*/) ||
6043           (dif2(pos_new,Transitdijunction1[itd1][i].pos())+(pos_new.t()-Transitdijunction1[itd1][i].x_t())*(pos_new.t()-Transitdijunction1[itd1][i].x_t()) > 0.00000001)){
6044           Transitdijunction1[itd1][i].P(P_new);
6045           Transitdijunction1[itd1][i].pos(pos_new);
6046           Transitdijunction1[itd1][i].mass(
6047             Transitdijunction1[itd1][i].e()*Transitdijunction1[itd1][i].e()
6048             - Transitdijunction1[itd1][i].px()*Transitdijunction1[itd1][i].px()
6049             - Transitdijunction1[itd1][i].py()*Transitdijunction1[itd1][i].py()
6050             - Transitdijunction1[itd1][i].pz()*Transitdijunction1[itd1][i].pz());
6051           Transitdijunction1[itd1][i].mass( (Transitdijunction1[itd1][i].mass() >= 0.) ? sqrt(Transitdijunction1[itd1][i].mass()) : -sqrt(-Transitdijunction1[itd1][i].mass()) ); //don't need mass >0 for reco now
6052           EP_conserved = false;
6053         }
6054       }
6055     }
6056     for(int i=0; i<Transitdijunction1.at(itd1).size(); ++i){
6057       if((Transitdijunction1[itd1][i].PY_stat() == -21)){// && (Transitdijunction1[itd1][i].PY_dau2() > Transitdijunction1[itd1][i].PY_dau1())){
6058         Transitdijunction1[itd1][i].px(Transitdijunction1[itd1][i].px()/2.);
6059         Transitdijunction1[itd1][i].py(Transitdijunction1[itd1][i].py()/2.);
6060         Transitdijunction1[itd1][i].pz(Transitdijunction1[itd1][i].pz()/2.);
6061         Transitdijunction1[itd1][i].e( Transitdijunction1[itd1][i].e() /2.);
6062         Transitdijunction1[itd1][i].mass(Transitdijunction1[itd1][i].mass()/2.);
6063       }
6064     }
6065 
6066     /*JSINFO << "This is dijunction " << itd1+1 << " after:";
6067     for(int i = 0; i <  Transitdijunction1.at(itd1).size(); i++){
6068       vector<HHparton> temp = Transitdijunction1.at(itd1);
6069       std::cout  << i <<"   "<< temp.at(i).id() <<"   "<< temp.at(i).PY_stat() <<"   "<< temp.at(i).PY_par1() <<"   "<< temp.at(i).PY_par2() <<"   "
6070       << temp.at(i).PY_dau1() <<"   "<< temp.at(i).PY_dau2() << "  ( "<<  temp.at(i).col()<< " , " << temp.at(i).acol() << " ) "
6071       << "  ( "<<  temp.at(i).e()<< " , " << temp.at(i).px()<< " , " << temp.at(i).py()<< " , " << temp.at(i).pz() << " ) "
6072       << "  ( "<<  temp.at(i).t()<< " , " << temp.at(i).x()<< " , " << temp.at(i).y()<< " , " << temp.at(i).z() << " ) " << std::endl;
6073     }*/
6074   }
6075 
6076   //for transitsinglejunction1
6077   for(int its1 = 0; its1 < Transitsinglejunction1.size(); its1++){
6078     bool EP_conserved = false;
6079     while(!EP_conserved){
6080       EP_conserved = true;
6081       for(int i=0; i<Transitsinglejunction1.at(its1).size(); ++i){
6082         if(Transitsinglejunction1[its1][i].PY_stat() >= 0 && std::abs(Transitsinglejunction1[its1][i].id()) < 1000){continue;}
6083         FourVector P_new(0.,0.,0.,0.); FourVector pos_new(0.,0.,0.,0.);
6084         int jmax = (Transitsinglejunction1[its1][i].PY_dau2() > Transitsinglejunction1[its1][i].PY_dau1()) ? Transitsinglejunction1[its1][i].PY_dau2() : Transitsinglejunction1[its1][i].PY_dau1();
6085         for(int j=Transitsinglejunction1[its1][i].PY_dau1(); j<jmax+1; ++j){
6086           double n = double(j-Transitsinglejunction1[its1][i].PY_dau1())+1.;
6087           P_new.Set(P_new.x()+Transitsinglejunction1[its1][j].px(),P_new.y()+Transitsinglejunction1[its1][j].py(),P_new.z()+Transitsinglejunction1[its1][j].pz(),P_new.t()+Transitsinglejunction1[its1][j].e());
6088           pos_new.Set(pos_new.x()+(Transitsinglejunction1[its1][j].x()-pos_new.x())/n,pos_new.y()+(Transitsinglejunction1[its1][j].y()-pos_new.y())/n,pos_new.z()+(Transitsinglejunction1[its1][j].z()-pos_new.z())/n,pos_new.t()+(Transitsinglejunction1[its1][j].x_t()-pos_new.t())/n);
6089         }
6090         if((dif2(P_new,Transitsinglejunction1[its1][i].P())+(P_new.t()-Transitsinglejunction1[its1][i].e())*(P_new.t()-Transitsinglejunction1[its1][i].e()) > 0.00000001/*0.0001^2*/) ||
6091           (dif2(pos_new,Transitsinglejunction1[its1][i].pos())+(pos_new.t()-Transitsinglejunction1[its1][i].x_t())*(pos_new.t()-Transitsinglejunction1[its1][i].x_t()) > 0.00000001)){
6092           Transitsinglejunction1[its1][i].P(P_new); Transitsinglejunction1[its1][i].pos(pos_new);
6093           Transitsinglejunction1[its1][i].mass( Transitsinglejunction1[its1][i].e()*Transitsinglejunction1[its1][i].e()
6094             - Transitsinglejunction1[its1][i].px()*Transitsinglejunction1[its1][i].px() - Transitsinglejunction1[its1][i].py()*Transitsinglejunction1[its1][i].py() - Transitsinglejunction1[its1][i].pz()*Transitsinglejunction1[its1][i].pz() );
6095           Transitsinglejunction1[its1][i].mass( (Transitsinglejunction1[its1][i].mass() >= 0.) ? sqrt(Transitsinglejunction1[its1][i].mass()) : -sqrt(-Transitsinglejunction1[its1][i].mass()) ); //don't need mass >0 for reco now
6096           EP_conserved = false;
6097         }
6098       }
6099     }
6100     for(int i=0; i<Transitsinglejunction1.at(its1).size(); ++i){
6101       if((Transitsinglejunction1[its1][i].PY_stat() == -21)){// && (Transitsinglejunction1[its1][i].PY_dau2() > Transitsinglejunction1[its1][i].PY_dau1())){
6102         Transitsinglejunction1[its1][i].px(Transitsinglejunction1[its1][i].px()/2.);
6103         Transitsinglejunction1[its1][i].py(Transitsinglejunction1[its1][i].py()/2.);
6104         Transitsinglejunction1[its1][i].pz(Transitsinglejunction1[its1][i].pz()/2.);
6105         Transitsinglejunction1[its1][i].e( Transitsinglejunction1[its1][i].e() /2.);
6106         Transitsinglejunction1[its1][i].mass(Transitsinglejunction1[its1][i].mass()/2.);
6107       }
6108     }
6109   }
6110 
6111   // make sure that there is enough energy in the system, such that the dijunctions can be hadronized
6112   // this is a rare case
6113   for(int itagdij1 = 0; itagdij1 < Transitdijunction1.size(); itagdij1++ ){
6114     double baryon_mass_scaling = 1.25;
6115     double mass_baryons = Transitdijunction1.at(itagdij1).at(0).mass() + Transitdijunction1.at(itagdij1).at(1).mass();
6116     double m1 = pythia.particleData.m0(std::abs(Transitdijunction1.at(itagdij1).at(0).id()));
6117     double m2 = pythia.particleData.m0(std::abs(Transitdijunction1.at(itagdij1).at(1).id()));
6118     if(mass_baryons < baryon_mass_scaling*(m1+m2)){
6119       //find fake gluon
6120       double new_gluon_mass = 2.*xmq;
6121       for(int itagdij2 = 0; itagdij2 < Transitdijunction1.at(itagdij1).size(); itagdij2++){
6122         HHparton p = Transitdijunction1.at(itagdij1).at(itagdij2);
6123         if(p.id() == 21){
6124           new_gluon_mass = p.mass()+baryon_mass_scaling*(m1+m2)-mass_baryons;
6125           p.mass(new_gluon_mass);
6126           double energy_new = std::sqrt(p.px()*p.px() + p.py()*p.py() + p.pz()*p.pz() + p.mass()*p.mass());
6127           p.e(energy_new);
6128           Transitdijunction1.at(itagdij1).at(itagdij2).mass(p.mass());
6129           Transitdijunction1.at(itagdij1).at(itagdij2).e(p.e());
6130         }
6131       }
6132       //find fake (anti-)quarks
6133       for(int itagdij2 = 0; itagdij2 < Transitdijunction1.at(itagdij1).size(); itagdij2++){
6134         HHparton p = Transitdijunction1.at(itagdij1).at(itagdij2);
6135         if(p.PY_stat() == -21 && std::abs(p.id()) < 6){
6136           p.mass(new_gluon_mass/2.);
6137           double energy_new = std::sqrt(p.px()*p.px() + p.py()*p.py() + p.pz()*p.pz() + p.mass()*p.mass());
6138           p.e(energy_new);
6139         }
6140         if(p.PY_stat() == -11 && std::abs(p.id()) > 1000){
6141           p.mass(p.mass()+(baryon_mass_scaling*(m1+m2)-mass_baryons)/2.);
6142           double energy_new = std::sqrt(p.px()*p.px() + p.py()*p.py() + p.pz()*p.pz() + p.mass()*p.mass());
6143           p.e(energy_new);
6144         }
6145       }
6146     }
6147   }
6148 
6149   for(int itagdij1 = 0; itagdij1 < Transitdijunction1.size(); itagdij1++ ){
6150     for(int itagdij2 = 0; itagdij2 < Transitdijunction1.at(itagdij1).size(); itagdij2++){
6151       WaitingLineforPY.push_back(Transitdijunction1.at(itagdij1).at(itagdij2));
6152     }
6153   }
6154 
6155   //dignostic measure{Transitdijunction1}
6156   /*int icheck2 = 0;
6157   std::cout <<endl<< " the order of data is eNum >> id >> stat >> par1 >> par2 >> dau1 >> dau2 "<< endl;
6158   for(int icheck1 = 0; icheck1 <  Transitdijunction1.size(); icheck1++ ){
6159     for(int i = 0; i <  Transitdijunction1.at(icheck1).size(); i++){
6160       vector<HHparton> temp = Transitdijunction1.at(icheck1);
6161       std::cout  << icheck2 <<"   "<< temp.at(i).id() <<"   "<< temp.at(i).PY_stat() <<"   "<< temp.at(i).PY_par1() <<"   "<< temp.at(i).PY_par2() <<"   "
6162       << temp.at(i).PY_dau1() <<"   "<< temp.at(i).PY_dau2() << "  ( "<<  temp.at(i).col()<< " , " << temp.at(i).acol() << " ) " <<endl;
6163       icheck2++;
6164     }
6165   }*/
6166 
6167   // make sure that there is enough energy in the system, such that the junctions can be hadronized
6168   // this is a rare case
6169   for(int itagsj1 = 0; itagsj1 < Transitsinglejunction1.size(); itagsj1++ ){
6170     double baryon_mass_scaling = 1.15;
6171     double mass_baryon = Transitsinglejunction1.at(itagsj1).at(0).mass();
6172     double m1 = pythia.particleData.m0(std::abs(Transitsinglejunction1.at(itagsj1).at(0).id()));
6173 
6174     if(mass_baryon < baryon_mass_scaling*m1){
6175       double baryon_mass_correction = baryon_mass_scaling*m1-mass_baryon;
6176       for(int itagsj2 = 0; itagsj2 < Transitsinglejunction1.at(itagsj1).size(); itagsj2++){
6177         if(std::abs(Transitsinglejunction1.at(itagsj1).at(itagsj2).id()) < 6){
6178           HHparton p = Transitsinglejunction1.at(itagsj1).at(itagsj2);
6179           p.mass(p.mass()+baryon_mass_correction/3.);
6180           double energy_new = std::sqrt(p.px()*p.px() + p.py()*p.py() + p.pz()*p.pz() + p.mass()*p.mass());
6181           p.e(energy_new);
6182           Transitsinglejunction1.at(itagsj1).at(itagsj2).mass(p.mass());
6183           Transitsinglejunction1.at(itagsj1).at(itagsj2).e(p.e());
6184         }
6185       }
6186 
6187       HHparton p = Transitsinglejunction1.at(itagsj1).at(0);
6188       p.mass(baryon_mass_scaling*m1);
6189       double energy_new = std::sqrt(p.px()*p.px() + p.py()*p.py() + p.pz()*p.pz() + p.mass()*p.mass());
6190       p.e(energy_new);
6191       Transitsinglejunction1.at(itagsj1).at(0).mass(p.mass());
6192       Transitsinglejunction1.at(itagsj1).at(0).e(p.e());
6193     }
6194   }
6195 
6196 
6197   for(int itagsj1 = 0; itagsj1 < Transitsinglejunction1.size(); itagsj1++ ){
6198     for(int itagsj2 = 0; itagsj2 < Transitsinglejunction1.at(itagsj1).size(); itagsj2++){
6199       WaitingLineforPY.push_back(Transitsinglejunction1.at(itagsj1).at(itagsj2));
6200     }
6201   }
6202 
6203   /*for(int i=0; i<WaitingLineforPY.size(); i++) {
6204     std::cout << WaitingLineforPY[i].id() << "," << WaitingLineforPY[i].col() << "," << WaitingLineforPY[i].acol() << "," << WaitingLineforPY[i].PY_par1() << "," << WaitingLineforPY[i].PY_par2() << std::endl;
6205   }*/
6206 
6207   for(int ifins = 0; ifins < finalstring.size(); ifins++){
6208     WaitingLineforPY.push_back(finalstring.at(ifins));
6209   }
6210 
6211   /*std::cout <<endl<<" Let's check final entry before PY!!"<<endl;
6212   std::cout <<endl<< " the order of data is eNum >> id >> stat >> par1 >> par2 >> dau1 >> dau2 >> (col, acol) >> x_t"<< endl;
6213   for(int fincheck = 0; fincheck < WaitingLineforPY.size(); fincheck++){
6214     vector<HHparton> temp = WaitingLineforPY;
6215     std::cout  << fincheck <<"   "<< temp.at(fincheck).id() <<"   "<< temp.at(fincheck).PY_stat() <<"   "<< temp.at(fincheck).PY_par1() <<"   "<< temp.at(fincheck).PY_par2() <<"   "
6216     << temp.at(fincheck).PY_dau1() <<"   "<< temp.at(fincheck).PY_dau2() << "  ( "<<  temp.at(fincheck).col()<< " , " << temp.at(fincheck).acol() << " )   " << temp.at(fincheck).x_t()<<endl;
6217   }*/
6218 
6219   for(int ifin = 0; ifin < WaitingLineforPY.size(); ifin++){
6220     SP_prepremn.add(WaitingLineforPY[ifin]);
6221   }
6222 
6223   Tempjunctions.clear(); // clear these informations for next running
6224   JuncStructure.clear();
6225   realjuncindice.clear();
6226   IMStructure1.clear();
6227   Dijunction1.clear();
6228   DijunctionInfo1.clear();
6229   Recombearly1.clear();
6230   Tailoredstring1.clear();
6231   finalstring.clear();
6232   Transitdijunction1.clear();
6233   Transitsinglejunction1.clear();
6234   WaitingLineforPY.clear();
6235   Tempsorting1.clear();
6236 }
6237 
6238 //function to hand partons/strings and hadron resonances (and various other color neutral and colored objects) to Pythia8
6239 bool HybridHadronization::invoke_py(){
6240 
6241     Event& event = pythia.event;
6242 
6243     //should have been checked before call, but if there are no partons/hadrons to deal with, just exit without invoking pythia
6244     if(HH_pyremn.num() + HH_hadrons.num() == 0){return true;}
6245 
6246     //first things first, need to reindex py_remn; just need to increment ALL by one
6247     //also restoring original id for color octet particles (or other 'odd' colored particles)
6248     for(int i=0; i<HH_pyremn.num(); ++i){
6249         HH_pyremn[i].PY_par1(HH_pyremn[i].PY_par1()+1); HH_pyremn[i].PY_par2(HH_pyremn[i].PY_par2()+1);
6250         HH_pyremn[i].PY_dau1(HH_pyremn[i].PY_dau1()+1); HH_pyremn[i].PY_dau2(HH_pyremn[i].PY_dau2()+1);
6251         if(HH_pyremn[i].PY_origid() != 0) {HH_pyremn[i].id( HH_pyremn[i].PY_origid());}
6252     }
6253 
6254     bool need_hadronization = true; bool success = true;
6255     int attempt = 0;
6256     while(need_hadronization){
6257         //incrementing attempt number
6258         ++attempt;
6259 
6260         //resetting PYTHIA event record, so that this event can be filled
6261         event.reset();
6262     HH_pythia_hadrons.clear();
6263 
6264         //number of partons/hadrons/particles handed to pythia
6265         int size_input = 0;
6266 
6267         //keeping track of partons from py_remn and hadrons into the event
6268         std::vector<int> eve_to_had; eve_to_had.push_back(0);
6269 
6270         //filling PYTHIA event record with the partons from this event
6271     int dijuncflag = 0;
6272     bool case1 = true;
6273     bool case2 = true;
6274     bool case3 = true;
6275     bool case4 = true;
6276     bool case5 = true;
6277     bool case6 = true;
6278         for(int i=0; i<HH_pyremn.num(); ++i){
6279       // code part to hadronize junctions and dijunctions separately
6280       // if fake pythia baryon (=junction or anti-junction) increment by one
6281       if(abs(HH_pyremn[i].id()) > 1112 && HH_pyremn[i].PY_tag1() !=0 && HH_pyremn[i].PY_tag2() !=0 && HH_pyremn[i].PY_tag3() !=0) {
6282         dijuncflag++;
6283       }
6284       // this first part is for the hadronization of junctions/anti-junctions
6285       if((dijuncflag == 1 && abs(HH_pyremn[i].id())<100 && HH_pyremn[i].PY_par1() == 0 && HH_pyremn[i].PY_par2() == 0)
6286         || (dijuncflag == 2 && abs(HH_pyremn[i-1].id()) < 100)) {
6287         size_input = event.size()-1;
6288         //event.listJunctions();
6289         //event.list();
6290         case1 &= pythia.next();
6291         //event.list();
6292         set_spacetime_for_pythia_hadrons(event,size_input,eve_to_had,attempt,case1,false,false);
6293         event.reset();
6294         eve_to_had.clear();
6295         if(dijuncflag == 1){dijuncflag=0;}
6296         if(dijuncflag == 2){dijuncflag=1;}
6297       }
6298       // if we are past two junctions, check if they are back-to-back;
6299       if(dijuncflag == 2) {
6300         if(abs(HH_pyremn[i-1].id())>1112){dijuncflag=3;}  // if yes, increment to 3; we are now inside a dijunction
6301         else{dijuncflag = 1;}  // no dijunction, must be a single one, step back to counter 1
6302       }
6303       // code red: we only reach this if we have reached the end of a dijunction; it's either another fake baryon or something without mother or daughter tags
6304       // this second part is for the hadronization of di-junctions
6305       if(dijuncflag == 4 || (HH_pyremn[i].PY_par1() == 0 && HH_pyremn[i].PY_par2() == 0 && HH_pyremn[i].PY_dau1() == 0 && HH_pyremn[i].PY_dau2() == 0 && dijuncflag == 3)) {
6306         // hadronize event here (which is only one dijunction); need to copy all the code that calls pythia AND refers to event.xxx up here
6307         size_input = event.size()-1;
6308         //event.listJunctions();
6309         //event.list();
6310         case2 &= pythia.next();
6311         //event.list();
6312         set_spacetime_for_pythia_hadrons(event,size_input,eve_to_had,attempt,case2,false,false);
6313         event.reset();
6314         eve_to_had.clear();
6315         if(dijuncflag == 4){dijuncflag=1;}else{dijuncflag=0;}
6316       }
6317 
6318             //append( id, status, mother1, mother2, daughter1, daughter2, col, acol, px, py, pz, e, m)
6319             event.append(HH_pyremn[i].id(),HH_pyremn[i].PY_stat(),HH_pyremn[i].PY_par1(),HH_pyremn[i].PY_par2(),HH_pyremn[i].PY_dau1(),HH_pyremn[i].PY_dau2(),
6320             HH_pyremn[i].col(),HH_pyremn[i].acol(),HH_pyremn[i].px(),HH_pyremn[i].py(),HH_pyremn[i].pz(),HH_pyremn[i].e(),HH_pyremn[i].mass());
6321       //JSINFO << HH_pyremn[i].id()<<","<<HH_pyremn[i].PY_stat()<<","<<HH_pyremn[i].PY_par1()<<","<<HH_pyremn[i].PY_par2()<<","<<HH_pyremn[i].PY_dau1()<<","<<HH_pyremn[i].PY_dau2()<<","<<
6322             //  HH_pyremn[i].col()<<","<<HH_pyremn[i].acol()<<","<<HH_pyremn[i].px()<<","<<HH_pyremn[i].py()<<","<<HH_pyremn[i].pz()<<","<<HH_pyremn[i].e()<<","<<HH_pyremn[i].mass();
6323             event[event.size()-1].vProd(HH_pyremn[i].x(), HH_pyremn[i].y(), HH_pyremn[i].z(), HH_pyremn[i].x_t());
6324             //for junction mother, adding junction to list manually for color tracing appendJunction(int kind, int col0, int col1, int col2);
6325             if(std::abs(event[event.size()-1].id()) > 1112){
6326                 event.appendJunction(((event[event.size()-1].id()>0) ? 1 : 2), HH_pyremn[i].PY_tag1(), HH_pyremn[i].PY_tag2(), HH_pyremn[i].PY_tag3());
6327             }
6328             eve_to_had.push_back(-i-1);
6329         }
6330 
6331     size_input = event.size()-1;
6332         //make PYTHIA hadronize this event, if it fails then retry N=10 times... (PYTHIA can and will rarely fail, without concern)
6333         //if this fails more than 10 times, we may retry this event starting back before recombination (some number of times)
6334     //event.listJunctions();
6335     //event.list();
6336     case3 &= pythia.next();
6337     //event.list();
6338     set_spacetime_for_pythia_hadrons(event,size_input,eve_to_had,attempt,case3,false,false);
6339     event.reset();
6340     eve_to_had.clear();
6341 
6342     //if we want to decay particles in pythia we have to do it separately for hadrons from recombination, otherwise the
6343     //information about the origin is lost
6344     //adding in hadrons/leptons/other colorless particles too...
6345     if(reco_hadrons_pythia){
6346       //reco hadrons
6347       for(int i=0; i<HH_hadrons.num(); ++i){
6348         if(HH_hadrons[i].is_final() && HH_hadrons[i].is_recohad() && HH_hadrons[i].is_shsh()){
6349                 //to make sure mass is set appropriately
6350                 double massnow = HH_hadrons[i].e()*HH_hadrons[i].e() -
6351                                 (HH_hadrons[i].px()*HH_hadrons[i].px() + HH_hadrons[i].py()*HH_hadrons[i].py() + HH_hadrons[i].pz()*HH_hadrons[i].pz());
6352                 massnow = (massnow >= 0.) ? sqrt(massnow) : -sqrt(-massnow);
6353                 event.append(HH_hadrons[i].id(),81,0,0,HH_hadrons[i].px(),HH_hadrons[i].py(),HH_hadrons[i].pz(),HH_hadrons[i].e(),massnow);
6354                 event[event.size()-1].vProd(HH_hadrons[i].x(), HH_hadrons[i].y(), HH_hadrons[i].z(), HH_hadrons[i].x_t());
6355                 eve_to_had.push_back(i+1);
6356             }
6357       }
6358       case4 &= pythia.next();
6359       set_spacetime_for_pythia_hadrons(event,size_input,eve_to_had,attempt,case4,true,true);
6360       event.reset();
6361       eve_to_had.clear();
6362 
6363       for(int i=0; i<HH_hadrons.num(); ++i){
6364         if(HH_hadrons[i].is_final() && HH_hadrons[i].is_recohad() && HH_hadrons[i].is_shth()){
6365                 //to make sure mass is set appropriately
6366                 double massnow = HH_hadrons[i].e()*HH_hadrons[i].e() -
6367                                 (HH_hadrons[i].px()*HH_hadrons[i].px() + HH_hadrons[i].py()*HH_hadrons[i].py() + HH_hadrons[i].pz()*HH_hadrons[i].pz());
6368                 massnow = (massnow >= 0.) ? sqrt(massnow) : -sqrt(-massnow);
6369                 event.append(HH_hadrons[i].id(),81,0,0,HH_hadrons[i].px(),HH_hadrons[i].py(),HH_hadrons[i].pz(),HH_hadrons[i].e(),massnow);
6370                 event[event.size()-1].vProd(HH_hadrons[i].x(), HH_hadrons[i].y(), HH_hadrons[i].z(), HH_hadrons[i].x_t());
6371                 eve_to_had.push_back(i+1);
6372             }
6373       }
6374       case5 &= pythia.next();
6375       set_spacetime_for_pythia_hadrons(event,size_input,eve_to_had,attempt,case5,true,false);
6376       event.reset();
6377       eve_to_had.clear();
6378 
6379       for(int i=0; i<HH_hadrons.num(); ++i){
6380         if(HH_hadrons[i].is_final() && !HH_hadrons[i].is_recohad()){
6381                 //to make sure mass is set appropriately
6382                 double massnow = HH_hadrons[i].e()*HH_hadrons[i].e() -
6383                                 (HH_hadrons[i].px()*HH_hadrons[i].px() + HH_hadrons[i].py()*HH_hadrons[i].py() + HH_hadrons[i].pz()*HH_hadrons[i].pz());
6384                 massnow = (massnow >= 0.) ? sqrt(massnow) : -sqrt(-massnow);
6385                 event.append(HH_hadrons[i].id(),81,0,0,HH_hadrons[i].px(),HH_hadrons[i].py(),HH_hadrons[i].pz(),HH_hadrons[i].e(),massnow);
6386                 event[event.size()-1].vProd(HH_hadrons[i].x(), HH_hadrons[i].y(), HH_hadrons[i].z(), HH_hadrons[i].x_t());
6387                 eve_to_had.push_back(i+1);
6388             }
6389       }
6390       case6 &= pythia.next();
6391       set_spacetime_for_pythia_hadrons(event,size_input,eve_to_had,attempt,case6,false,false);
6392       event.reset();
6393       eve_to_had.clear();
6394     }
6395 
6396         if(!case1 || !case2 || !case3 || !case4 || !case5 || !case6){
6397           if(attempt > 4){need_hadronization = false; success = false; break;}
6398           continue;
6399         }
6400         //this event has been successfully hadronized (hopefully), put all final state particles into HH_pythia_hadrons; set is_final=true for these
6401     //this is done in set_spacetime_for_pythia_hadrons() and in DoHadronization all these Hadrons are written to HH_hadrons
6402         need_hadronization = false;
6403   }
6404     return success;
6405 }
6406 
6407 void HybridHadronization::set_spacetime_for_pythia_hadrons(Pythia8::Event &event, int &size_input, std::vector<int> &eve_to_had, int pythia_attempt, bool find_positions, bool is_recohadron, bool recohadron_shsh) {
6408   // directly return if hadronization in pythia failed, such that nothing is added to HH_pythia_hadrons
6409   if(!find_positions) {
6410     return;
6411   }
6412 
6413   vector<HHhadron> final_hadrons_from_pythia; // hadrons with preliminary set positions (average positions along string segment)
6414 
6415   vector<int> Case1_hadron_idx; // index of the hadron from case 1 below
6416   vector<int> Case1_parton1_idx; // index of the parton1 from case 1 below
6417   vector<int> Case1_parton2_idx; // index of the parton2 from case 1 below
6418 
6419   vector<int> Case2_hadron_idx; // index of the hadron from case 2 below
6420   vector<int> Case2_parton1_idx; // index of the parton1 from case 2 below
6421   vector<int> Case2_parton2_idx; // index of the parton2 from case 2 below
6422   vector<int> Case2_parton3_idx; // index of the parton3 from case 2 below
6423   vector<double> Case2_junction_center; // store the center position of the junction in element 0=t,1=x,2=y,3=z
6424   // this works only for the current implementation, where the junctions are handed over to pythia one after the other
6425 
6426 
6427   vector<int> Case3_hadron_idx; // index of the hadron from case 3 below
6428   vector<int> Case3_parton1_idx; // index of the parton1 from case 3 below
6429   vector<int> Case3_parton2_idx; // index of the parton2 from case 3 below
6430   vector<double> Case3_partons_center; // store the center position of the partons
6431 
6432   bool compute_more_precise_positions = true;
6433   bool warn_could_not_find_positions = false;
6434 
6435   for(int hadron_idx = 1; hadron_idx < event.size(); hadron_idx++) {
6436     if(event[hadron_idx].isFinal()) { //take only final hadrons from pythia
6437       //convert pythia hadron to HHhadron
6438       HHhadron hadron_out; //a number of other tags need to be set from the parent (either hadron or string)
6439       hadron_out.is_final(true);
6440       hadron_out.id(event[hadron_idx].id());
6441       hadron_out.mass(event[hadron_idx].m());
6442       hadron_out.px(event[hadron_idx].px());
6443       hadron_out.py(event[hadron_idx].py());
6444       hadron_out.pz(event[hadron_idx].pz());
6445       hadron_out.e(event[hadron_idx].e());
6446 
6447       //since using inbuilt pythia mother/daughter functions will segfault 'occasionally', going to code it in by hand.
6448             //this could probably be done more efficiently, but it's good enough for now...
6449       std::vector<int> mothers;
6450       //using a stack system to fill mothers
6451             std::vector<int> stack;
6452       //filling stack with initial mothers
6453       if((event[hadron_idx].mother1() < event[hadron_idx].mother2()) && (event[hadron_idx].mother1() > 0)
6454         && (std::abs(event[hadron_idx].status()) >= 81) && (std::abs(event[hadron_idx].status()) <= 86)){
6455               for(int hadron_parent = event[hadron_idx].mother1(); hadron_parent <= event[hadron_idx].mother2(); ++hadron_parent) {
6456           stack.push_back(hadron_parent);
6457         }
6458             }else if((event[hadron_idx].mother2() > 0) && (event[hadron_idx].mother1() != event[hadron_idx].mother2())) {
6459               stack.push_back(event[hadron_idx].mother1());
6460         stack.push_back(event[hadron_idx].mother2());
6461           }else if(event[hadron_idx].mother1() > 0) {
6462               stack.push_back(event[hadron_idx].mother1());
6463           }else{mothers.push_back(hadron_idx);} //setting it as its own mother if there are no mothers (pythia didn't decay a directly input hadron...)
6464 
6465       //filling the stack with any valid mothers of the 'current' stack element
6466             //then we check the 'current' stack element to see if it's a valid mother (0<element<=n_input), if so, we write it to mothers
6467             while(stack.size() > 0){
6468               int current = stack.back();
6469         stack.pop_back();
6470               if((event[current].mother1() < event[current].mother2()) && (event[current].mother1() > 0) &&
6471                 (std::abs(event[current].status()) >= 81) && (std::abs(event[current].status()) <= 86)) {
6472                   for(int hadron_parent = event[current].mother1(); hadron_parent <= event[current].mother2(); ++hadron_parent) {
6473             stack.push_back(hadron_parent);
6474           }
6475                 }else if((event[current].mother2() > 0) && (event[current].mother1() != event[current].mother2())) {
6476                   stack.push_back(event[current].mother1());
6477           stack.push_back(event[current].mother2());
6478                 }else if(event[current].mother1() > 0) {
6479                     stack.push_back(event[current].mother1());
6480                 }
6481               if((current > 0) && (current <= size_input)) {mothers.push_back(current);}
6482             }
6483 
6484       //just in case...
6485             if(mothers.size() == 0) {mothers.push_back(hadron_idx);}
6486 
6487       //sorting and removing duplicate entries
6488             std::sort(mothers.begin(), mothers.end());
6489       mothers.erase(std::unique(mothers.begin(), mothers.end()), mothers.end());
6490 
6491       //first, using mothers to determine if this hadron was formed via recombination, or by string fragmentation
6492             if(mothers[0] <= HH_pyremn.num()){
6493         hadron_out.is_strhad(true);
6494       }else{
6495         hadron_out.is_recohad(true);
6496       }
6497 
6498       //lastly, using mothers (except fake) in original input to determine if this is a shower-shower or shower-thermal hadron
6499             bool is_therm(false);
6500             for(int hadron_parent = 0; hadron_parent < mothers.size(); ++hadron_parent) {
6501               if(mothers[hadron_parent] <= HH_pyremn.num()) {
6502                   if(HH_pyremn[mothers[hadron_parent]-1].orig() != -1) {
6503             hadron_out.add_par(mothers[hadron_parent]-1);
6504             if(HH_pyremn[mothers[hadron_parent]-1].is_thermal()) {is_therm = true;}
6505           }
6506                 }else if(mothers[hadron_parent] < size_input){ //shouldn't actually need to check, but doing so just in case.
6507                     hadron_out.parh(eve_to_had[mothers[hadron_parent]]-1);
6508           if(HH_hadrons[hadron_out.parh()].is_shth()) {is_therm = true;}
6509                 }
6510             }
6511             if(is_therm) {
6512         hadron_out.is_shth(true);
6513       }else{
6514         hadron_out.is_shsh(true);
6515       }
6516 
6517       if(is_recohadron && recohadron_shsh){
6518         hadron_out.is_recohad(true);
6519         hadron_out.is_shsh(true);
6520         hadron_out.is_shth(false);
6521       } else if(is_recohadron && !recohadron_shsh){
6522         hadron_out.is_recohad(true);
6523         hadron_out.is_shsh(false);
6524         hadron_out.is_shth(true);
6525       }
6526 
6527       int hadron_col = event[hadron_idx].col();
6528       int hadron_acol = event[hadron_idx].acol();
6529       bool info_found = false; bool col_known = false; bool acol_known = false;
6530 
6531       //3 main cases: col!=acol, col==acol!=0, col==acol==0
6532       if(hadron_col != hadron_acol) { //col!=acol -> this hadron should trace back to a single gluon; find it and grab its spacetime info
6533         for(int irem = 0; irem < HH_pyremn.num(); ++irem) {
6534                     if(((HH_pyremn[irem].col() == hadron_col) && (HH_pyremn[irem].acol() == hadron_acol))
6535             || ((HH_pyremn[irem].col() == hadron_acol) && (HH_pyremn[irem].acol() == hadron_col))) {//alter for glu loops
6536                         if(HH_pyremn[irem].PY_stat()<=0) {continue;}
6537                         hadron_out.x(HH_pyremn[irem].x());
6538             hadron_out.y(HH_pyremn[irem].y());
6539             hadron_out.z(HH_pyremn[irem].z());
6540             hadron_out.x_t(HH_pyremn[irem].x_t());
6541                         info_found = true;
6542                     }
6543                 }
6544         if(!info_found) {
6545           //this is bad; could either be a hadron from *multiple* segments, or still from a single gluon under color reconnections - OR BOTH!
6546                   //this is a first-order handling to find all the intermediate partons using the input partons -
6547                     //it really should be done using pythia's history, but should suffice for most cases, for now...
6548                     //will apply Dijkstra to the partons in the current string to find the shortest path from hadron_col to hadron_acol
6549 
6550           //start by finding the partons with the col/acol tags
6551                     int ptn1 = -1; int ptn2 = -1;
6552                     for(int irem = 0; irem < HH_pyremn.num(); ++irem) {
6553                         if((HH_pyremn[irem].col() == hadron_col) && (HH_pyremn[irem].PY_stat() > 0)) {ptn1 = irem;}
6554                         if((HH_pyremn[irem].acol() == hadron_acol) && (HH_pyremn[irem].PY_stat() > 0)) {ptn2 = irem;}
6555                         if((ptn1 >= 0) && (ptn2 >= 0)){break;}
6556                     }
6557 
6558           //if ptn1 or ptn2 < 0, then we're giving up on this hadron (needs pythia history to properly reconstruct the mother parton(s))
6559                     //otherwise, we'll trace along the string from one parton end to the other (using Dijkstra) to find all mother partons
6560                     if((ptn1 >= 0) && (ptn2 >= 0)){
6561                         //for 0th order approx, we'll just average the positions of the known parton ends
6562                         double pos_x, pos_y, pos_z, pos_t; pos_x = 0.; pos_y = 0.; pos_z = 0.; pos_t = 0.;
6563                         pos_x += HH_pyremn[ptn1].x(); pos_y += HH_pyremn[ptn1].y(); pos_z += HH_pyremn[ptn1].z(); pos_t += HH_pyremn[ptn1].x_t();
6564                         pos_x += HH_pyremn[ptn2].x(); pos_y += HH_pyremn[ptn2].y(); pos_z += HH_pyremn[ptn2].z(); pos_t += HH_pyremn[ptn2].x_t();
6565                         pos_x /= 2.; pos_y /= 2.; pos_z /= 2.; pos_t /= 2.;
6566                         hadron_out.x(pos_x); hadron_out.y(pos_y); hadron_out.z(pos_z); hadron_out.x_t(pos_t);
6567                         info_found = true;
6568             Case1_hadron_idx.push_back(hadron_idx);
6569             Case1_parton1_idx.push_back(ptn1);
6570             Case1_parton2_idx.push_back(ptn2);
6571                     }
6572         }
6573       }else if((hadron_col == hadron_acol) && (hadron_col != 0)) { //col==acol -> this hadron traces back to a string segment; find the two partons and interpolate position
6574         //there are 2 cases here - an easy case where the color tags match the original partons, and a hard case where we need to trace history
6575                 int ptn1 = 0; int ptn2 = 0; int ptn3 = 0;
6576         bool col_found = false; bool acol_found = false; bool ptn3_found = false;
6577                 while(ptn1 < HH_pyremn.num()) {if((HH_pyremn[ptn1].col() == hadron_col) && (HH_pyremn[ptn1].PY_stat() > 0)) {col_found =true; break;} ++ptn1;}
6578                 while(ptn2 < HH_pyremn.num()) {if((HH_pyremn[ptn2].acol() == hadron_acol)&& (HH_pyremn[ptn2].PY_stat() > 0)) {acol_found=true; break;} ++ptn2;}
6579 
6580                 col_known = col_found; acol_known = acol_found;
6581         //if we don't find color/anticolor tags in input partons, we'll need to trace along pythia event/history to find either/both
6582                 //we can grab what pythia claims are the mothers, then search that for the color tag, which should return ONE candidate
6583                 //repeat this until event_i <= HH_pyremn.num() - this will be our input
6584                 //would it be better to start at the beginning, grab everything that doesn't have a terminal color tag in a hadron, and trace those to respective hadron(s)?
6585 
6586         //since these *only* should happen in junction systems at the junction, use the junction list to find the other 2 color tags, then find those in orig. ptns!
6587                 if(!col_found){
6588                     //find the junction with matching color, grab the other 2
6589                     int coll[2] = {0,0};
6590                     for(int iJ = 0; iJ < pythia.event.sizeJunction(); ++iJ) {
6591             for(int iC = 0; iC < 3; ++iC) {
6592                           if(pythia.event.colJunction(iJ,iC) == hadron_col) {
6593                             if(iC == 0) {coll[0] = pythia.event.colJunction(iJ,1); coll[1] = pythia.event.colJunction(iJ,2);}
6594                             else if(iC == 1) {coll[0] = pythia.event.colJunction(iJ,0); coll[1] = pythia.event.colJunction(iJ,2);}
6595                             else{coll[0] = pythia.event.colJunction(iJ,0); coll[1] = pythia.event.colJunction(iJ,1);}
6596                             col_found=true; break;
6597                         }
6598                     }
6599             if(col_found) {break;}
6600           }
6601           //since pythia refuses to keep track of initial junctions given to it, we'll do it manually
6602                     if(!col_found) {
6603                         for(int irem = 0; irem < HH_pyremn.num(); ++irem) {
6604               if(std::abs(HH_pyremn[irem].id()) > 1112) {
6605                               if(     HH_pyremn[irem].PY_tag1() == hadron_col) {coll[0] = HH_pyremn[irem].PY_tag2(); coll[1] = HH_pyremn[irem].PY_tag3(); col_found = true; break;}
6606                               else if(HH_pyremn[irem].PY_tag2() == hadron_col) {coll[0] = HH_pyremn[irem].PY_tag1(); coll[1] = HH_pyremn[irem].PY_tag3(); col_found = true; break;}
6607                               else if(HH_pyremn[irem].PY_tag3() == hadron_col) {coll[0] = HH_pyremn[irem].PY_tag1(); coll[1] = HH_pyremn[irem].PY_tag2(); col_found = true; break;}
6608                           }
6609             }
6610                     }
6611                     //now we know the color tags needed, we look for them.
6612                     if(col_found) {
6613                         bool found_tags[2] = {0,0}; ptn1 = 0;
6614                         while(ptn1<HH_pyremn.num()) {if((HH_pyremn[ptn1].acol() == coll[0]) && (HH_pyremn[ptn1].PY_stat() > 0)) {found_tags[0] = true; break;} ++ptn1;}
6615                         while(ptn3<HH_pyremn.num()) {if((HH_pyremn[ptn3].acol() == coll[1]) && (HH_pyremn[ptn2].PY_stat() > 0)) {found_tags[1] = true; break;} ++ptn3;}
6616                         if(found_tags[0] && found_tags[1]) {ptn3_found = true;}
6617                     }
6618                 }
6619         if(!acol_found) {
6620                     //check to see if there's already 3 partons - if so, then we need a warning/error!
6621                     if(ptn3_found) {JSWARN << "A hadron was found with more than 3 partonic parents for space-time info!";}
6622                     //otherwise, works just like above...
6623                     int coll[2] = {0,0};
6624                     for(int iJ = 0; iJ < pythia.event.sizeJunction(); ++iJ) {
6625             for(int iC = 0; iC < 3; ++iC) {
6626                           if(pythia.event.colJunction(iJ,iC) == hadron_acol) {
6627                               if(iC == 0) {coll[0] = pythia.event.colJunction(iJ,1); coll[1] = pythia.event.colJunction(iJ,2);}
6628                               else if(iC == 1) {coll[0] = pythia.event.colJunction(iJ,0); coll[1] = pythia.event.colJunction(iJ,2);}
6629                               else{coll[0] = pythia.event.colJunction(iJ,0); coll[1] = pythia.event.colJunction(iJ,1);}
6630                               acol_found = true; break;
6631                           }
6632                       }
6633             if(acol_found) {break;}
6634           }
6635                     //since pythia refuses to keep track of initial junctions given to it, we'll do it manually
6636                     if(!acol_found) {
6637                         for(int irem = 0; irem < HH_pyremn.num(); ++irem) {
6638               if(std::abs(HH_pyremn[irem].id()) > 1112) {
6639                               if(     HH_pyremn[irem].PY_tag1() == hadron_col) {coll[0] = HH_pyremn[irem].PY_tag2(); coll[1] = HH_pyremn[irem].PY_tag3(); acol_found = true; break;}
6640                               else if(HH_pyremn[irem].PY_tag2() == hadron_col) {coll[0] = HH_pyremn[irem].PY_tag1(); coll[1] = HH_pyremn[irem].PY_tag3(); acol_found = true; break;}
6641                               else if(HH_pyremn[irem].PY_tag3() == hadron_col) {coll[0] = HH_pyremn[irem].PY_tag1(); coll[1] = HH_pyremn[irem].PY_tag2(); acol_found = true; break;}
6642                           }
6643             }
6644                     }
6645                     //now we know the anti-color tags needed, we look for them.
6646                     if(acol_found){
6647                         bool found_tags[2] = {0,0}; ptn2 = 0;
6648                         while(ptn2<HH_pyremn.num()){if((HH_pyremn[ptn2].col()==coll[0]) && (HH_pyremn[ptn1].PY_stat()>0)){found_tags[0]=true; break;} ++ptn2;}
6649                         while(ptn3<HH_pyremn.num()){if((HH_pyremn[ptn3].col()==coll[1]) && (HH_pyremn[ptn2].PY_stat()>0)){found_tags[1]=true; break;} ++ptn3;}
6650                         if(found_tags[0] && found_tags[1]){ptn3_found=true;}
6651                     }
6652                 }
6653 
6654         col_known = col_found; acol_known = acol_found;
6655                 //turning off warning iff things work
6656                 if(col_found && acol_found) {info_found = true;}
6657 
6658         //setting position from found partons
6659                 double pos_x, pos_y, pos_z, pos_t; pos_x=0.; pos_y=0.; pos_z=0.; pos_t=0.;
6660                 pos_x += HH_pyremn[ptn1].x(); pos_y += HH_pyremn[ptn1].y(); pos_z += HH_pyremn[ptn1].z(); pos_t += HH_pyremn[ptn1].x_t();
6661                 pos_x += HH_pyremn[ptn2].x(); pos_y += HH_pyremn[ptn2].y(); pos_z += HH_pyremn[ptn2].z(); pos_t += HH_pyremn[ptn2].x_t();
6662         Case2_hadron_idx.push_back(hadron_idx);
6663         Case2_parton1_idx.push_back(ptn1);
6664         Case2_parton2_idx.push_back(ptn2);
6665                 if(ptn3_found){
6666                     pos_x += HH_pyremn[ptn3].x(); pos_y += HH_pyremn[ptn3].y(); pos_z += HH_pyremn[ptn3].z(); pos_t += HH_pyremn[ptn3].x_t();
6667                     pos_x /= 3.; pos_y /= 3.; pos_z /= 3.; pos_t /= 3.;
6668           Case2_parton3_idx.push_back(ptn3);
6669           Case2_junction_center = {pos_t,pos_x,pos_y,pos_z};
6670                 }else{
6671           pos_x /= 2.; pos_y /= 2.; pos_z /= 2.; pos_t /= 2.;
6672           Case2_parton3_idx.push_back(-1);
6673         }
6674                 hadron_out.x(pos_x); hadron_out.y(pos_y); hadron_out.z(pos_z); hadron_out.x_t(pos_t);
6675       }else if((hadron_col == hadron_acol) && (hadron_col == 0)) { //col==acol==0 -> same as previous, but pythia didn't give color tag since this was from a short string q-qbar
6676         double avg_x, avg_y, avg_z, avg_t; avg_x=0.; avg_y=0.; avg_z=0.; avg_t=0.;
6677                 int n_ptns = 0; //should come out to 2 in the end, but keeping track just in case.
6678         bool found_first_q_or_qbar = false; bool found_second_q_or_qbar = false;
6679         for(int imot = 0; imot < mothers.size(); ++imot) {
6680           if(mothers[imot] <= HH_pyremn.num()) {
6681             info_found = true; //if no mothers, then no position, and throw error!
6682                       avg_x += HH_pyremn[mothers[imot]-1].x(); avg_y += HH_pyremn[mothers[imot]-1].y(); avg_z += HH_pyremn[mothers[imot]-1].z(); avg_t += HH_pyremn[mothers[imot]-1].x_t();
6683                       ++n_ptns;
6684             if(std::abs(HH_pyremn[mothers[imot]-1].id()) < 7 && !found_first_q_or_qbar) {
6685               Case3_parton1_idx.push_back(mothers[imot]-1);
6686               found_first_q_or_qbar = true;
6687             } else if(std::abs(HH_pyremn[mothers[imot]-1].id()) < 7 && !found_second_q_or_qbar && found_first_q_or_qbar) {
6688               Case3_parton2_idx.push_back(mothers[imot]-1);
6689               found_second_q_or_qbar = true;
6690             }
6691                   }
6692         }
6693         if(found_first_q_or_qbar && found_second_q_or_qbar) {
6694           Case3_hadron_idx.push_back(hadron_idx);
6695         }
6696         if(found_first_q_or_qbar && !found_second_q_or_qbar) {
6697           Case3_parton1_idx.pop_back();
6698         }
6699                 if(n_ptns > 0) {
6700           avg_x /= double(n_ptns); avg_y /= double(n_ptns); avg_z /= double(n_ptns); avg_t /= double(n_ptns);
6701           Case3_partons_center = {avg_t,avg_x,avg_y,avg_z};
6702         }
6703                 hadron_out.x(avg_x); hadron_out.y(avg_y); hadron_out.z(avg_z); hadron_out.x_t(avg_t);
6704       }
6705       if(!info_found) {
6706         compute_more_precise_positions = false;
6707         warn_could_not_find_positions = true;
6708               hadron_out.x(0.); hadron_out.y(0.); hadron_out.z(0.); hadron_out.x_t(0.);
6709       }
6710 
6711         //the mother procedure might skip some partons if there are junctions involved
6712         //this can be 'repaired' by taking a 'mother' parton, then checking over all the partons in its string! (both adding to parents / checking if thermal)
6713           //this is done in hadronization calling function, after invoke_py function is finished
6714         final_hadrons_from_pythia.push_back(hadron_out);
6715     }
6716   }
6717 
6718   //warn about not found position for hadrons only once per function call
6719   if(warn_could_not_find_positions && GetXMLElementInt({"Afterburner", "include_fragmentation_hadrons"}) == 1) {
6720     VERBOSE(2) << "Could not find the spacetime information for hadron in pythia event (string fragmentation attempt ="
6721     << pythia_attempt << "), set it to (0,0,0,0)";
6722   }
6723 
6724   //now let's do it a bit more precise and distribute the positions along the string segments instead of using the average
6725   if(compute_more_precise_positions) {
6726     //find the more precise positions for case 1
6727     //have to find the hadrons from the same string segment
6728     vector<int> Case1_unique_parton1_idx = Case1_parton1_idx;
6729     std::sort(Case1_unique_parton1_idx.begin(), Case1_unique_parton1_idx.end());
6730     Case1_unique_parton1_idx.erase(std::unique(Case1_unique_parton1_idx.begin(), Case1_unique_parton1_idx.end()), Case1_unique_parton1_idx.end());
6731     // go through string segments
6732     for(int string_seg = 0; string_seg < Case1_unique_parton1_idx.size(); string_seg++) {
6733       int segment_parton1_idx = Case1_unique_parton1_idx.at(string_seg);
6734 
6735       // select the hadrons from the string which need position modification
6736       vector<int> segment_hadron_idx;
6737       for(int iHad = 0; iHad < Case1_hadron_idx.size(); iHad++) {
6738         if(Case1_parton1_idx.at(iHad) == segment_parton1_idx) {
6739           segment_hadron_idx.push_back(iHad);
6740         }
6741       }
6742 
6743       // modify the hadron positions from the current string
6744       int number_hadrons_segment = segment_hadron_idx.size();
6745       if(number_hadrons_segment > 1) {
6746         for(int iHad = 0; iHad < number_hadrons_segment; iHad++) {
6747           int parton1_index = Case1_parton1_idx.at(segment_hadron_idx.at(iHad));
6748           int parton2_index = Case1_parton2_idx.at(segment_hadron_idx.at(iHad));
6749           int current_hadron_idx = segment_hadron_idx.at(iHad);
6750 
6751           //get the positions of the two partons at the ends of the string segment
6752           double pos_x_ptn1 = HH_pyremn[parton1_index].x();
6753           double pos_y_ptn1 = HH_pyremn[parton1_index].y();
6754           double pos_z_ptn1 = HH_pyremn[parton1_index].z();
6755           double pos_t_ptn1 = HH_pyremn[parton1_index].x_t();
6756           double pos_x_ptn2 = HH_pyremn[parton2_index].x();
6757           double pos_y_ptn2 = HH_pyremn[parton2_index].y();
6758           double pos_z_ptn2 = HH_pyremn[parton2_index].z();
6759           double pos_t_ptn2 = HH_pyremn[parton2_index].x_t();
6760 
6761           double delta_x = (pos_x_ptn2 - pos_x_ptn1) / (number_hadrons_segment+1);
6762           double delta_y = (pos_y_ptn2 - pos_y_ptn1) / (number_hadrons_segment+1);
6763           double delta_z = (pos_z_ptn2 - pos_z_ptn1) / (number_hadrons_segment+1);
6764           double delta_t = (pos_t_ptn2 - pos_t_ptn1) / (number_hadrons_segment+1);
6765 
6766           double had_x = pos_x_ptn1 + (iHad+1) * delta_x;
6767           double had_y = pos_y_ptn1 + (iHad+1) * delta_y;
6768           double had_z = pos_z_ptn1 + (iHad+1) * delta_z;
6769           double had_t = pos_t_ptn1 + (iHad+1) * delta_t;
6770 
6771           //set the hadron to the new position along the string segment
6772           final_hadrons_from_pythia.at(current_hadron_idx).x(had_x);
6773           final_hadrons_from_pythia.at(current_hadron_idx).y(had_y);
6774           final_hadrons_from_pythia.at(current_hadron_idx).z(had_z);
6775           final_hadrons_from_pythia.at(current_hadron_idx).x_t(had_t);
6776         }
6777       }
6778     }
6779 
6780     //find the more precise positions for case 2
6781     //have to find the hadrons from the same string segment
6782     vector<int> Case2_unique_parton1_idx = Case2_parton1_idx;
6783     std::sort(Case2_unique_parton1_idx.begin(), Case2_unique_parton1_idx.end());
6784     Case2_unique_parton1_idx.erase(std::unique(Case2_unique_parton1_idx.begin(), Case2_unique_parton1_idx.end()), Case2_unique_parton1_idx.end());
6785 
6786     // go through string segments or junction legs
6787     for(int string_seg = 0; string_seg < Case2_unique_parton1_idx.size(); string_seg++) {
6788       int segment_parton1_idx = Case2_unique_parton1_idx.at(string_seg);
6789 
6790       // select the hadrons from the string which need position modification
6791       vector<int> segment_hadron_idx;
6792       for(int iHad = 0; iHad < Case2_hadron_idx.size(); iHad++) {
6793         if(Case2_parton1_idx.at(iHad) == segment_parton1_idx) {
6794           segment_hadron_idx.push_back(iHad);
6795         }
6796       }
6797 
6798       // modify the hadron positions from the current string
6799       int number_hadrons_segment = segment_hadron_idx.size();
6800       if(number_hadrons_segment > 1) { // in case of a string segment use average position if only one hadron, in case of junction use center (nothing to do here)
6801         for(int iHad = 0; iHad < number_hadrons_segment; iHad++) {
6802           int parton1_index = Case2_parton1_idx.at(segment_hadron_idx.at(iHad));
6803           int parton2_index = Case2_parton2_idx.at(segment_hadron_idx.at(iHad));
6804           int parton3_index = Case2_parton3_idx.at(segment_hadron_idx.at(iHad));
6805           int current_hadron_idx = segment_hadron_idx.at(iHad);
6806 
6807           if((parton3_index == -1) && (Case2_junction_center.size() == 0)) { // this is the case where we have two partons at the string segment ends
6808             //get the positions of the two partons at the ends of the string segment
6809             double pos_x_ptn1 = HH_pyremn[parton1_index].x();
6810             double pos_y_ptn1 = HH_pyremn[parton1_index].y();
6811             double pos_z_ptn1 = HH_pyremn[parton1_index].z();
6812             double pos_t_ptn1 = HH_pyremn[parton1_index].x_t();
6813             double pos_x_ptn2 = HH_pyremn[parton2_index].x();
6814             double pos_y_ptn2 = HH_pyremn[parton2_index].y();
6815             double pos_z_ptn2 = HH_pyremn[parton2_index].z();
6816             double pos_t_ptn2 = HH_pyremn[parton2_index].x_t();
6817 
6818             double delta_x = (pos_x_ptn2 - pos_x_ptn1) / (number_hadrons_segment+1);
6819             double delta_y = (pos_y_ptn2 - pos_y_ptn1) / (number_hadrons_segment+1);
6820             double delta_z = (pos_z_ptn2 - pos_z_ptn1) / (number_hadrons_segment+1);
6821             double delta_t = (pos_t_ptn2 - pos_t_ptn1) / (number_hadrons_segment+1);
6822 
6823             double had_x = pos_x_ptn1 + (iHad+1) * delta_x;
6824             double had_y = pos_y_ptn1 + (iHad+1) * delta_y;
6825             double had_z = pos_z_ptn1 + (iHad+1) * delta_z;
6826             double had_t = pos_t_ptn1 + (iHad+1) * delta_t;
6827 
6828             //set the hadron to the new position along the string segment
6829             final_hadrons_from_pythia.at(current_hadron_idx).x(had_x);
6830             final_hadrons_from_pythia.at(current_hadron_idx).y(had_y);
6831             final_hadrons_from_pythia.at(current_hadron_idx).z(had_z);
6832             final_hadrons_from_pythia.at(current_hadron_idx).x_t(had_t);
6833           } else if(parton3_index > -1 && Case2_junction_center.size() != 0) { // this is the case with a junction / antijunction
6834             // compute the leg vectors (center is origin)
6835             vector<double> leg1_vec = {HH_pyremn[parton1_index].x_t()-Case2_junction_center[0],
6836                                       HH_pyremn[parton1_index].x()-Case2_junction_center[1],
6837                                       HH_pyremn[parton1_index].y()-Case2_junction_center[2],
6838                                       HH_pyremn[parton1_index].z()-Case2_junction_center[3]};
6839             vector<double> leg2_vec = {HH_pyremn[parton2_index].x_t()-Case2_junction_center[0],
6840                                       HH_pyremn[parton2_index].x()-Case2_junction_center[1],
6841                                       HH_pyremn[parton2_index].y()-Case2_junction_center[2],
6842                                       HH_pyremn[parton2_index].z()-Case2_junction_center[3]};
6843             vector<double> leg3_vec = {HH_pyremn[parton3_index].x_t()-Case2_junction_center[0],
6844                                       HH_pyremn[parton3_index].x()-Case2_junction_center[1],
6845                                       HH_pyremn[parton3_index].y()-Case2_junction_center[2],
6846                                       HH_pyremn[parton3_index].z()-Case2_junction_center[3]};
6847             double abs_leg1 = std::sqrt(leg1_vec[0]*leg1_vec[0] + leg1_vec[1]*leg1_vec[1] + leg1_vec[2]*leg1_vec[2] + leg1_vec[3]*leg1_vec[3]);
6848             double abs_leg2 = std::sqrt(leg2_vec[0]*leg2_vec[0] + leg2_vec[1]*leg2_vec[1] + leg2_vec[2]*leg2_vec[2] + leg2_vec[3]*leg2_vec[3]);
6849             double abs_leg3 = std::sqrt(leg3_vec[0]*leg3_vec[0] + leg3_vec[1]*leg3_vec[1] + leg3_vec[2]*leg3_vec[2] + leg3_vec[3]*leg3_vec[3]);
6850             if(abs_leg1 <= 1e-6 || abs_leg2 <= 1e-6 || abs_leg3 <= 1e-6) {continue;}
6851             double L = abs_leg1 + abs_leg2 + abs_leg3;
6852             double delta_l = L / (number_hadrons_segment + 1); // inter hadron distance
6853             double distance = delta_l + iHad; // center -> end leg1, center -> end leg2, center -> end leg3
6854             double had_t, had_x, had_y, had_z;
6855             if(distance <= abs_leg1) {
6856               had_t = leg1_vec[0] * (distance / abs_leg1);
6857               had_x = leg1_vec[1] * (distance / abs_leg1);
6858               had_y = leg1_vec[2] * (distance / abs_leg1);
6859               had_z = leg1_vec[3] * (distance / abs_leg1);
6860             } else if((abs_leg1 < distance) && (distance <= abs_leg1+abs_leg2)) {
6861               had_t = leg2_vec[0] * ((distance - abs_leg1) / abs_leg2);
6862               had_x = leg2_vec[1] * ((distance - abs_leg1) / abs_leg2);
6863               had_y = leg2_vec[2] * ((distance - abs_leg1) / abs_leg2);
6864               had_z = leg2_vec[3] * ((distance - abs_leg1) / abs_leg2);
6865             } else { // (abs_leg1+abs_leg2 < distance) && (distance <= L)
6866               had_t = leg3_vec[0] * ((distance - abs_leg1 - abs_leg2) / abs_leg3);
6867               had_x = leg3_vec[1] * ((distance - abs_leg1 - abs_leg2) / abs_leg3);
6868               had_y = leg3_vec[2] * ((distance - abs_leg1 - abs_leg2) / abs_leg3);
6869               had_z = leg3_vec[3] * ((distance - abs_leg1 - abs_leg2) / abs_leg3);
6870             }
6871             //set the hadron to the new position along the string segment
6872             final_hadrons_from_pythia.at(current_hadron_idx).x(had_x);
6873             final_hadrons_from_pythia.at(current_hadron_idx).y(had_y);
6874             final_hadrons_from_pythia.at(current_hadron_idx).z(had_z);
6875             final_hadrons_from_pythia.at(current_hadron_idx).x_t(had_t);
6876           }
6877         }
6878       }
6879     }
6880 
6881     //find the more precise positions for case 3
6882     //have to find the hadrons from the same string segment
6883     vector<int> Case3_unique_parton1_idx = Case3_parton1_idx;
6884     std::sort(Case3_unique_parton1_idx.begin(), Case3_unique_parton1_idx.end());
6885     Case3_unique_parton1_idx.erase(std::unique(Case3_unique_parton1_idx.begin(), Case3_unique_parton1_idx.end()), Case3_unique_parton1_idx.end());
6886     // go through string segments
6887     for(int string_seg = 0; string_seg < Case3_unique_parton1_idx.size(); string_seg++) {
6888       int segment_parton1_idx = Case3_unique_parton1_idx.at(string_seg);
6889 
6890       // select the hadrons from the string which need position modification
6891       vector<int> segment_hadron_idx;
6892       for(int iHad = 0; iHad < Case3_hadron_idx.size(); iHad++) {
6893         if(Case3_parton1_idx.at(iHad) == segment_parton1_idx) {
6894           segment_hadron_idx.push_back(iHad);
6895         }
6896       }
6897 
6898       // modify the hadron positions from the current string
6899       int number_hadrons_segment = segment_hadron_idx.size();
6900       if(number_hadrons_segment > 1) {
6901         for(int iHad = 0; iHad < number_hadrons_segment; iHad++) {
6902           int parton1_index = Case3_parton1_idx.at(segment_hadron_idx.at(iHad));
6903           int parton2_index = Case3_parton2_idx.at(segment_hadron_idx.at(iHad));
6904           int current_hadron_idx = segment_hadron_idx.at(iHad);
6905 
6906           vector<double> seg1_vec = {HH_pyremn[parton1_index].x_t()-Case3_partons_center[0],
6907                                       HH_pyremn[parton1_index].x()-Case3_partons_center[1],
6908                                       HH_pyremn[parton1_index].y()-Case3_partons_center[2],
6909                                       HH_pyremn[parton1_index].z()-Case3_partons_center[3]};
6910           vector<double> seg2_vec = {HH_pyremn[parton2_index].x_t()-Case3_partons_center[0],
6911                                       HH_pyremn[parton2_index].x()-Case3_partons_center[1],
6912                                       HH_pyremn[parton2_index].y()-Case3_partons_center[2],
6913                                       HH_pyremn[parton2_index].z()-Case3_partons_center[3]};
6914           double abs_seg1 = std::sqrt(seg1_vec[0]*seg1_vec[0] + seg1_vec[1]*seg1_vec[1] + seg1_vec[2]*seg1_vec[2] + seg1_vec[3]*seg1_vec[3]);
6915           double abs_seg2 = std::sqrt(seg2_vec[0]*seg2_vec[0] + seg2_vec[1]*seg2_vec[1] + seg2_vec[2]*seg2_vec[2] + seg2_vec[3]*seg2_vec[3]);
6916           if(abs_seg1 <= 1e-6 || abs_seg2 <= 1e-6) {continue;}
6917           double L = abs_seg1 + abs_seg2;
6918           double delta_l = L / (number_hadrons_segment + 1); // inter hadron distance
6919           double distance = delta_l + iHad; // center -> end seg1, center -> end seg2
6920           double had_t, had_x, had_y, had_z;
6921           if(distance <= abs_seg1) {
6922               had_t = seg1_vec[0] * (distance / abs_seg1);
6923               had_x = seg1_vec[1] * (distance / abs_seg1);
6924               had_y = seg1_vec[2] * (distance / abs_seg1);
6925               had_z = seg1_vec[3] * (distance / abs_seg1);
6926           } else { // (abs_leg1 < distance) && (distance <= abs_leg1+abs_leg2)
6927               had_t = seg2_vec[0] * ((distance - abs_seg1) / abs_seg2);
6928               had_x = seg2_vec[1] * ((distance - abs_seg1) / abs_seg2);
6929               had_y = seg2_vec[2] * ((distance - abs_seg1) / abs_seg2);
6930               had_z = seg2_vec[3] * ((distance - abs_seg1) / abs_seg2);
6931           }
6932           //set the hadron to the new position along the string segment
6933           final_hadrons_from_pythia.at(current_hadron_idx).x(had_x);
6934           final_hadrons_from_pythia.at(current_hadron_idx).y(had_y);
6935           final_hadrons_from_pythia.at(current_hadron_idx).z(had_z);
6936           final_hadrons_from_pythia.at(current_hadron_idx).x_t(had_t);
6937         }
6938       }
6939     }
6940   }
6941 
6942   //finally add the hadrons with position information to the HH_hadrons
6943   //the mother procedure might skip some partons if there are junctions involved
6944     //this can be 'repaired' by taking a 'mother' parton, then checking over all the partons in its string! (both adding to parents / checking if thermal)
6945   //this is done in hadronization calling function, after this invoke_py function is finished
6946   for(int hadron_idx = 0; hadron_idx < final_hadrons_from_pythia.size(); hadron_idx++) {
6947     HH_pythia_hadrons.add(final_hadrons_from_pythia[hadron_idx]);
6948   }
6949 }
6950 
6951 void HybridHadronization::bring_hadrons_to_mass_shell(hadron_collection& HH_hadrons) {
6952   //to calc. E conservation violation
6953   //double Ebefore = 0.; double Eafter = 0.; double pTbefore = 0.; double pTafter = 0.;
6954   //for(int iHad=0; iHad<HH_hadrons.num(); ++iHad){if(!HH_hadrons[iHad].is_final()){continue;} Ebefore += HH_hadrons[iHad].e(); pTbefore += HH_hadrons[iHad].pt();}
6955   //std::cout << std::setprecision(5);
6956   //std::ofstream eviol; std::ofstream echg; std::ofstream ptchg;
6957   //eviol.open("Evio_hadrons.dat", std::ios::app); echg.open("Echg_hadrons.dat", std::ios::app); ptchg.open("ptchg_hadrons.dat", std::ios::app);
6958 
6959     //hadron mass adjust
6960     double osf = 1e-6;
6961     for(int iHad=0; iHad<HH_hadrons.num(); ++iHad){
6962       //if this isn't a final state hadron, there's no point in fixing it.
6963       if(!HH_hadrons[iHad].is_final()){continue;}
6964 
6965         //need hadron mass and pdg (pythia) mass to check
6966         double hadmass = HH_hadrons[iHad].mass();
6967     double m1 = pythia.particleData.m0(HH_hadrons[iHad].id());
6968         //if this hadron doesn't need to be fixed, then we skip it
6969         if(!(std::abs(hadmass - m1)/m1 > osf)){continue;}
6970 
6971         //this hadron needs fixing, so we prepare to find a partner hadron to adjust with it
6972         int partner = -1;
6973 
6974         //if this hadron has colors, then we can use that info to fix it
6975         if(HH_hadrons[iHad].cols.size() > 0){
6976           //looking through the hadron list to find another hadron with the same color tag.
6977           for(int jHad = 0; jHad < HH_hadrons.num(); ++jHad){
6978             if(!HH_hadrons[jHad].is_final()){continue;} //do not want a non-final hadron
6979             if(iHad == jHad){continue;} //needs to be a different hadron
6980         double m2 = pythia.particleData.m0(HH_hadrons[jHad].id());
6981         double pair_mass = std::sqrt((HH_hadrons[iHad].e() + HH_hadrons[jHad].e())*(HH_hadrons[iHad].e() + HH_hadrons[jHad].e())
6982             - (HH_hadrons[iHad].px() + HH_hadrons[jHad].px())*(HH_hadrons[iHad].px() + HH_hadrons[jHad].px())
6983             - (HH_hadrons[iHad].py() + HH_hadrons[jHad].py())*(HH_hadrons[iHad].py() + HH_hadrons[jHad].py())
6984             - (HH_hadrons[iHad].pz() + HH_hadrons[jHad].pz())*(HH_hadrons[iHad].pz() + HH_hadrons[jHad].pz()));
6985         // variabele to compute the squared momentum difference of the partners
6986         // if this is too small the mass adjustment procedure would fail
6987         double momentum_diff = (HH_hadrons[iHad].px()-HH_hadrons[jHad].px())*(HH_hadrons[iHad].px()-HH_hadrons[jHad].px())
6988                       + (HH_hadrons[iHad].py()-HH_hadrons[jHad].py())*(HH_hadrons[iHad].py()-HH_hadrons[jHad].py())
6989                       + (HH_hadrons[iHad].pz()-HH_hadrons[jHad].pz())*(HH_hadrons[iHad].pz()-HH_hadrons[jHad].pz());
6990             if(HH_hadrons[jHad].cols.size() > 0){//if this hadron has color tags, check
6991           //JSINFO << "iHad = " << iHad << ", jHad = " << jHad << ", momentum_diff = " << momentum_diff << ", pair_mass - m1 - m2 = " << pair_mass-m1-m2;
6992               for(int icol = 0; icol < HH_hadrons[iHad].cols.size(); ++icol){
6993             for(int jcol = 0; jcol < HH_hadrons[jHad].cols.size(); ++jcol){
6994               if(!(HH_hadrons[iHad].col(icol) == HH_hadrons[jHad].col(jcol)) || momentum_diff < 1e-6 || (pair_mass < m1+m2)){continue;} //color not matching
6995                         //if the previous condition isn't met, that means the colors match!
6996                         partner = jHad; break;
6997                     }
6998             if(partner > -1){break;}
6999           }
7000             }
7001             if(partner > -1){break;}
7002           }
7003         }
7004 
7005         //ready to fix, if a partner has not been found, pick a close-by hadron
7006     //make sure that there is a relative momentum to reshuffle the masses
7007         if(partner == -1){
7008           //grabbing closest final state hadron before and after, if it exists
7009           int iprev = iHad-1; int inext = iHad+1;
7010           while(iprev >= 0){
7011         double m2 = pythia.particleData.m0(HH_hadrons[iprev].id());
7012         double pair_mass = std::sqrt((HH_hadrons[iHad].e() + HH_hadrons[iprev].e())*(HH_hadrons[iHad].e() + HH_hadrons[iprev].e())
7013             - (HH_hadrons[iHad].px() + HH_hadrons[iprev].px())*(HH_hadrons[iHad].px() + HH_hadrons[iprev].px())
7014             - (HH_hadrons[iHad].py() + HH_hadrons[iprev].py())*(HH_hadrons[iHad].py() + HH_hadrons[iprev].py())
7015             - (HH_hadrons[iHad].pz() + HH_hadrons[iprev].pz())*(HH_hadrons[iHad].pz() + HH_hadrons[iprev].pz()));
7016         double momentum_diff = (HH_hadrons[iHad].px()-HH_hadrons[iprev].px())*(HH_hadrons[iHad].px()-HH_hadrons[iprev].px())
7017                       + (HH_hadrons[iHad].py()-HH_hadrons[iprev].py())*(HH_hadrons[iHad].py()-HH_hadrons[iprev].py())
7018                       + (HH_hadrons[iHad].pz()-HH_hadrons[iprev].pz())*(HH_hadrons[iHad].pz()-HH_hadrons[iprev].pz());
7019         if(HH_hadrons[iprev].is_final() && momentum_diff >= 1e-6 && pair_mass >= m1+m2){break;}
7020         --iprev;
7021       }
7022             while(inext < HH_hadrons.num()){
7023         double m2 = pythia.particleData.m0(HH_hadrons[inext].id());
7024         double pair_mass = std::sqrt((HH_hadrons[iHad].e() + HH_hadrons[inext].e())*(HH_hadrons[iHad].e() + HH_hadrons[inext].e())
7025             - (HH_hadrons[iHad].px() + HH_hadrons[inext].px())*(HH_hadrons[iHad].px() + HH_hadrons[inext].px())
7026             - (HH_hadrons[iHad].py() + HH_hadrons[inext].py())*(HH_hadrons[iHad].py() + HH_hadrons[inext].py())
7027             - (HH_hadrons[iHad].pz() + HH_hadrons[inext].pz())*(HH_hadrons[iHad].pz() + HH_hadrons[inext].pz()));
7028         double momentum_diff = (HH_hadrons[iHad].px()-HH_hadrons[inext].px())*(HH_hadrons[iHad].px()-HH_hadrons[inext].px())
7029                       + (HH_hadrons[iHad].py()-HH_hadrons[inext].py())*(HH_hadrons[iHad].py()-HH_hadrons[inext].py())
7030                       + (HH_hadrons[iHad].pz()-HH_hadrons[inext].pz())*(HH_hadrons[iHad].pz()-HH_hadrons[inext].pz());
7031         if(HH_hadrons[inext].is_final() && momentum_diff >= 1e-6 && pair_mass >= m1+m2){break;}
7032         ++inext;
7033       }
7034 
7035           //if there is no closest before, then grab closest after
7036           //or if no closest after, then grab closest before
7037           //if both exist, grab the one that's closest, unless both are the same in which case grab the one after
7038           if(iprev < 0){partner = inext;}
7039           else if(inext >= HH_hadrons.num()){partner = iprev;}
7040           else{partner = (inext - iHad <= iHad - iprev) ? inext : iprev;}
7041 
7042       if((partner >= HH_hadrons.num()) || (partner < 0)) {partner = -1;}
7043         }
7044 
7045     //choose the hadron with the smallest pair_mass - m1 - m2 value
7046     if(partner == -1){
7047       double minimum = 1e6;
7048       int partner_temporary = -1;
7049           for(int jHad = 0; jHad < HH_hadrons.num(); ++jHad){
7050         if(!HH_hadrons[jHad].is_final()){continue;} //do not want a non-final hadron
7051             if(iHad == jHad){continue;} //needs to be a different hadron
7052         double m2 = pythia.particleData.m0(HH_hadrons[jHad].id());
7053         double pair_mass = std::sqrt((HH_hadrons[iHad].e() + HH_hadrons[jHad].e())*(HH_hadrons[iHad].e() + HH_hadrons[jHad].e())
7054             - (HH_hadrons[iHad].px() + HH_hadrons[jHad].px())*(HH_hadrons[iHad].px() + HH_hadrons[jHad].px())
7055             - (HH_hadrons[iHad].py() + HH_hadrons[jHad].py())*(HH_hadrons[iHad].py() + HH_hadrons[jHad].py())
7056             - (HH_hadrons[iHad].pz() + HH_hadrons[jHad].pz())*(HH_hadrons[iHad].pz() + HH_hadrons[jHad].pz()));
7057         if(std::abs(pair_mass-m1-m2) < minimum){
7058           minimum = std::abs(pair_mass-m1-m2);
7059           partner_temporary = jHad;
7060         }
7061       }
7062       if(partner_temporary != -1){
7063         partner = partner_temporary;
7064       }
7065     }
7066 
7067         //by now, a partner *must* have been chosen - unless there's only 1 hadron in the event, which is BAD.
7068         //time to fix.
7069         //if somehow everything failed, just skip this hadron...
7070         if(partner == -1){continue;}
7071 
7072     //std::cout << "H1_before: " << iHad << ", " << HH_hadrons[iHad].id() << ", " << HH_hadrons[iHad].px() << ", " << HH_hadrons[iHad].py() << ", " << HH_hadrons[iHad].pz() << ", " << HH_hadrons[iHad].e() << "\n";
7073     //std::cout << "H2_before: " << partner << ", " << HH_hadrons[partner].id() << ", " << HH_hadrons[partner].px() << ", " << HH_hadrons[partner].py() << ", " << HH_hadrons[partner].pz() << ", " << HH_hadrons[partner].e() << "\n";
7074 
7075         //Psys
7076         FourVector Psys;
7077         Psys.Set(HH_hadrons[iHad].px()+HH_hadrons[partner].px(),HH_hadrons[iHad].py()+HH_hadrons[partner].py(),HH_hadrons[iHad].pz()+HH_hadrons[partner].pz(),HH_hadrons[iHad].e()+HH_hadrons[partner].e());
7078 
7079         //CM velocity
7080         FourVector beta;
7081         beta.Set(Psys.x()/Psys.t(),Psys.y()/Psys.t(),Psys.z()/Psys.t(),0.);
7082         beta.Set(beta.x(),beta.y(),beta.z(),1./(sqrt(1.-(beta.x()*beta.x() + beta.y()*beta.y() + beta.z()*beta.z()))));
7083 
7084         //boosting into CM frame
7085         FourVector p_CM[2]; p_CM[0] = HH_hadrons[iHad].boost_P(beta); p_CM[1] = HH_hadrons[partner].boost_P(beta);
7086 
7087         //if E1 + E2 >= m1 + m2, shift momenta
7088         double m2 = pythia.particleData.m0(HH_hadrons[partner].id());
7089         double Etot = p_CM[0].t() + p_CM[1].t();
7090         if(Etot < m1 + m2 + 0.00001){Etot = m1 + m2 + 0.00001; /*eviol << Etot - (p_CM[0].t() + p_CM[1].t()) << "\n";*/}//can't shift, violating E/P cons.
7091         double E1 = Etot/2. + ((m1*m1)-(m2*m2))/(2.*Etot);
7092         double E2 = Etot/2. - ((m1*m1)-(m2*m2))/(2.*Etot);
7093         double pmag = sqrt(p_CM[0].x()*p_CM[0].x() + p_CM[0].y()*p_CM[0].y() + p_CM[0].z()*p_CM[0].z());
7094         double fac = sqrt(Etot*Etot/4. + ((m1*m1)-(m2*m2))*((m1*m1)-(m2*m2))/(4.*Etot*Etot) - ((m1*m1)+(m2*m2))/2.)/pmag;
7095 
7096         //rescaling in CM frame
7097     p_CM[0].Set(fac*p_CM[0].x(), fac*p_CM[0].y(), fac*p_CM[0].z(), E1);
7098     p_CM[1].Set(fac*p_CM[1].x(), fac*p_CM[1].y(), fac*p_CM[1].z(), E2);
7099 
7100         //boosting back and setting hadron E,P to fixed values
7101     beta.Set(-beta.x(), -beta.y(), -beta.z(), 0.);
7102     beta.Set(beta.x(),beta.y(),beta.z(),1./(sqrt(1.-(beta.x()*beta.x() + beta.y()*beta.y() + beta.z()*beta.z()))));
7103         FourVector p_fin[2]; p_fin[0] = HHboost(beta, p_CM[0]); p_fin[1] = HHboost(beta, p_CM[1]);
7104         HH_hadrons[iHad].P(p_fin[0]); HH_hadrons[partner].P(p_fin[1]);
7105     HH_hadrons[iHad].mass(m1);
7106     HH_hadrons[partner].mass(m2);
7107 
7108     //std::cout << "H1_after: " << iHad << ", " << HH_hadrons[iHad].id() << ", " << HH_hadrons[iHad].px() << ", " << HH_hadrons[iHad].py() << ", " << HH_hadrons[iHad].pz() << ", " << HH_hadrons[iHad].e() << "\n";
7109     //std::cout << "H2_after: " << partner << ", " << HH_hadrons[partner].id() << ", " << HH_hadrons[partner].px() << ", " << HH_hadrons[partner].py() << ", " << HH_hadrons[partner].pz() << ", " << HH_hadrons[partner].e() << "\n";
7110   }
7111 
7112   //calc. Etot after
7113   //for(int iHad=0; iHad<HH_hadrons.num(); ++iHad){if(!HH_hadrons[iHad].is_final()){continue;} Eafter += HH_hadrons[iHad].e(); pTafter += HH_hadrons[iHad].pt();}
7114   //echg << Eafter-Ebefore << "\n"; ptchg << pTafter-pTbefore << "\n";
7115   //eviol.close(); echg.close(); ptchg.close();
7116 }
7117 
7118 void HybridHadronization::set_initial_parton_masses(parton_collection& HH_partons) {
7119   //to calc. E conservation violation
7120   /*double Ebefore = 0.; double Eafter = 0.; double pTbefore = 0.; double pTafter = 0.;
7121   for(int iPart=0; iPart<HH_partons.num(); ++iPart){Ebefore += HH_partons[iPart].e(); pTbefore += HH_partons[iPart].pt();}
7122   std::cout << std::setprecision(5);
7123   std::ofstream eviol; std::ofstream echg; std::ofstream ptchg;
7124   eviol.open("Evio_partons.dat", std::ios::app); echg.open("Echg_partons.dat", std::ios::app); ptchg.open("ptchg_partons.dat", std::ios::app);*/
7125 
7126   // case for only one parton in the event -> force to parton mass
7127   if(HH_partons.num() == 1) {
7128     HHparton parton = HH_partons[0];
7129     if(std::abs(parton.id()) < 6 && parton.mass() < pythia.particleData.m0(std::abs(parton.id()))) { // quark case
7130       parton.mass(pythia.particleData.m0(std::abs(parton.id())));
7131       parton.e(std::sqrt(parton.px()*parton.px() + parton.py()*parton.py() + parton.pz()*parton.pz() + parton.mass()*parton.mass()));
7132       HH_partons[0] = parton;
7133     } else if(parton.id() == 21 && parton.mass() < 2.*xmq + 0.001) { // gluon case (pythia has m_g = 0.)
7134       parton.mass(2.*xmq + 0.001);
7135       parton.e(std::sqrt(parton.px()*parton.px() + parton.py()*parton.py() + parton.pz()*parton.pz() + parton.mass()*parton.mass()));
7136       HH_partons[0] = parton;
7137     }
7138     return;
7139   }
7140 
7141     //parton mass adjust
7142     double osf = 1e-6;
7143     for(int iPart=0; iPart<HH_partons.num(); ++iPart){
7144       //if this isn't a final state parton, there's no point in fixing it.
7145         if ((HH_partons[iPart].id() != 21) && (std::abs(HH_partons[iPart].id()) > 5)){continue;}
7146 
7147         //need parton mass and pdg (pythia) mass to check
7148         double partmass = HH_partons[iPart].mass();
7149     double m1 = 0.;
7150     if(HH_partons[iPart].id() == 21){
7151       m1 = 2.*xmq + 0.001;
7152     } else if(std::abs(HH_partons[iPart].id()) < 3) {
7153       m1 = xmq;
7154     } else if(std::abs(HH_partons[iPart].id()) == 3) {
7155       m1 = xms;
7156     } else if(std::abs(HH_partons[iPart].id()) == 4) {
7157       m1 = xmc;
7158     } else if(std::abs(HH_partons[iPart].id()) == 5) {
7159       m1 = xmb;
7160     }
7161 
7162         //if this parton doesn't need to be fixed, then we skip it
7163         if((std::abs(partmass - m1)/m1 < osf) && (std::abs(HH_partons[iPart].id()) < 6)){continue;}
7164 
7165     if((HH_partons[iPart].id() == 21) && (partmass > m1)){continue;}
7166 
7167         //this parton needs fixing, so we prepare to find a partner to adjust with it
7168         int partner = -1;
7169 
7170         //looking through the parton list to find another parton with the same color tag.
7171         for(int jPart=0; jPart<HH_partons.num(); ++jPart){
7172       if(iPart == jPart || (std::abs(HH_partons[iPart].id()) > 5 && std::abs(HH_partons[iPart].id()) < 7)){continue;} //needs to be a different parton
7173       double m2 = 0.;
7174       if ((HH_partons[jPart].id() == 21) && (HH_partons[jPart].mass() < 2.*xmq + 0.001)){
7175         m2 = 2.*xmq + 0.001;
7176       } else if ((HH_partons[jPart].id() == 21) && (HH_partons[jPart].mass() >= 2.*xmq + 0.001)){
7177         m2 = HH_partons[jPart].mass();
7178       } else if(std::abs(HH_partons[jPart].id()) < 3) {
7179         m2 = xmq;
7180       } else if(std::abs(HH_partons[jPart].id()) == 3) {
7181         m2 = xms;
7182       } else if(std::abs(HH_partons[jPart].id()) == 4) {
7183         m2 = xmc;
7184       } else if(std::abs(HH_partons[jPart].id()) == 5) {
7185         m2 = xmb;
7186       }
7187       double pair_mass = std::sqrt((HH_partons[iPart].e() + HH_partons[jPart].e())*(HH_partons[iPart].e() + HH_partons[jPart].e())
7188             - (HH_partons[iPart].px() + HH_partons[jPart].px())*(HH_partons[iPart].px() + HH_partons[jPart].px())
7189             - (HH_partons[iPart].py() + HH_partons[jPart].py())*(HH_partons[iPart].py() + HH_partons[jPart].py())
7190             - (HH_partons[iPart].pz() + HH_partons[jPart].pz())*(HH_partons[iPart].pz() + HH_partons[jPart].pz()));
7191       // variabele to compute the squared momentum difference of the partners
7192       // if this is too small the mass adjustment procedure would fail
7193       double momentum_diff = (HH_partons[iPart].px()-HH_partons[jPart].px())*(HH_partons[iPart].px()-HH_partons[jPart].px())
7194                     + (HH_partons[iPart].py()-HH_partons[jPart].py())*(HH_partons[iPart].py()-HH_partons[jPart].py())
7195                     + (HH_partons[iPart].pz()-HH_partons[jPart].pz())*(HH_partons[iPart].pz()-HH_partons[jPart].pz());
7196       if(((HH_partons[iPart].col() == HH_partons[jPart].acol()) || (HH_partons[iPart].acol() == HH_partons[jPart].col())) && (momentum_diff > 1e-6) && (pair_mass >= m1+m2)){
7197         if((HH_partons[jPart].id() == 21) && (HH_partons[jPart].mass() < 2.*xmq + 0.001)) {
7198           partner = jPart;
7199           break;
7200         } else if ((std::abs(HH_partons[jPart].id()) < 3) && (std::abs(HH_partons[jPart].mass() - xmq)/xmq > osf)) {
7201           partner = jPart;
7202           break;
7203         } else if ((std::abs(HH_partons[jPart].id()) == 3) && (std::abs(HH_partons[jPart].mass() - xms)/xms > osf)) {
7204           partner = jPart;
7205           break;
7206         } else if ((std::abs(HH_partons[jPart].id()) == 4) && (std::abs(HH_partons[jPart].mass() - xmc)/xmc > osf)) {
7207           partner = jPart;
7208           break;
7209         } else if ((std::abs(HH_partons[jPart].id()) == 5) && (std::abs(HH_partons[jPart].mass() - xmb)/xmb > osf)) {
7210           partner = jPart;
7211           break;
7212         }
7213       }
7214     }
7215 
7216     // candidate for a parton with the smallest energy loss (if no partner is found)
7217     int iPartnerCandidate = -1;
7218     double energy_loss_tracking = 1e6; // just a large number
7219 
7220         //ready to fix, if a partner has not been found, pick a close-by parton
7221     //make sure that there is a relative momentum to reshuffle the masses
7222         if(partner == -1){
7223           //grabbing closest parton before and after, if it exists
7224           int iprev = iPart-1; int inext = iPart+1;
7225           while(iprev >= 0){
7226         double m2 = 0.;
7227         if ((HH_partons[iprev].id() == 21) && (HH_partons[iprev].mass() < 2.*xmq + 0.001)){
7228           m2 = 2.*xmq + 0.001;
7229         } else if ((HH_partons[iprev].id() == 21) && (HH_partons[iprev].mass() >= 2.*xmq + 0.001)){
7230           m2 = HH_partons[iprev].mass();
7231         } else if(std::abs(HH_partons[iprev].id()) < 3) {
7232           m2 = xmq;
7233         } else if(std::abs(HH_partons[iprev].id()) == 3) {
7234           m2 = xms;
7235         } else if(std::abs(HH_partons[iprev].id()) == 4) {
7236           m2 = xmc;
7237         } else if(std::abs(HH_partons[iprev].id()) == 5) {
7238           m2 = xmb;
7239         }
7240         double pair_mass = std::sqrt((HH_partons[iPart].e() + HH_partons[iprev].e())*(HH_partons[iPart].e() + HH_partons[iprev].e())
7241             - (HH_partons[iPart].px() + HH_partons[iprev].px())*(HH_partons[iPart].px() + HH_partons[iprev].px())
7242             - (HH_partons[iPart].py() + HH_partons[iprev].py())*(HH_partons[iPart].py() + HH_partons[iprev].py())
7243             - (HH_partons[iPart].pz() + HH_partons[iprev].pz())*(HH_partons[iPart].pz() + HH_partons[iprev].pz()));
7244         double momentum_diff = (HH_partons[iPart].px()-HH_partons[iprev].px())*(HH_partons[iPart].px()-HH_partons[iprev].px())
7245                       + (HH_partons[iPart].py()-HH_partons[iprev].py())*(HH_partons[iPart].py()-HH_partons[iprev].py())
7246                       + (HH_partons[iPart].pz()-HH_partons[iprev].pz())*(HH_partons[iPart].pz()-HH_partons[iprev].pz());
7247         if((momentum_diff > 1e-6) && (pair_mass >= m1+m2) && (std::abs(HH_partons[iprev].id()) < 6 || HH_partons[iprev].id() == 21)){
7248           if(energy_loss_tracking > std::abs(pair_mass - m1 - m2)) {
7249             energy_loss_tracking = std::abs(pair_mass - m1 - m2);
7250             iPartnerCandidate = iprev;
7251           }
7252           break;
7253         }
7254         --iprev;
7255       }
7256             while(inext < HH_partons.num()){
7257         double m2 = 0.;
7258         if ((HH_partons[inext].id() == 21) && (HH_partons[inext].mass() < 2.*xmq + 0.001)){
7259           m2 = 2.*xmq + 0.001;
7260         } else if ((HH_partons[inext].id() == 21) && (HH_partons[inext].mass() >= 2.*xmq + 0.001)){
7261           m2 = HH_partons[inext].mass();
7262         } else if(std::abs(HH_partons[inext].id()) < 3) {
7263           m2 = xmq;
7264         } else if(std::abs(HH_partons[inext].id()) == 3) {
7265           m2 = xms;
7266         } else if(std::abs(HH_partons[inext].id()) == 4) {
7267           m2 = xmc;
7268         } else if(std::abs(HH_partons[inext].id()) == 5) {
7269           m2 = xmb;
7270         }
7271         double pair_mass = std::sqrt((HH_partons[iPart].e() + HH_partons[inext].e())*(HH_partons[iPart].e() + HH_partons[inext].e())
7272             - (HH_partons[iPart].px() + HH_partons[inext].px())*(HH_partons[iPart].px() + HH_partons[inext].px())
7273             - (HH_partons[iPart].py() + HH_partons[inext].py())*(HH_partons[iPart].py() + HH_partons[inext].py())
7274             - (HH_partons[iPart].pz() + HH_partons[inext].pz())*(HH_partons[iPart].pz() + HH_partons[inext].pz()));
7275         double momentum_diff = (HH_partons[iPart].px()-HH_partons[inext].px())*(HH_partons[iPart].px()-HH_partons[inext].px())
7276                       + (HH_partons[iPart].py()-HH_partons[inext].py())*(HH_partons[iPart].py()-HH_partons[inext].py())
7277                       + (HH_partons[iPart].pz()-HH_partons[inext].pz())*(HH_partons[iPart].pz()-HH_partons[inext].pz());
7278         if((momentum_diff > 1e-6) && (pair_mass >= m1+m2) && (std::abs(HH_partons[inext].id()) < 6 || HH_partons[inext].id() == 21)){
7279           if(energy_loss_tracking > std::abs(pair_mass - m1 - m2)) {
7280             energy_loss_tracking = std::abs(pair_mass - m1 - m2);
7281             iPartnerCandidate = inext;
7282           }
7283           break;
7284         }
7285         ++inext;
7286       }
7287 
7288           //if there is no closest before, then grab closest after
7289           //or if no closest after, then grab closest before
7290           //if both exist, grab the one that's closest, unless both are the same in which case grab the one after
7291           if(iprev < 0){partner = inext;}
7292           else if(inext >= HH_partons.num()){partner = iprev;}
7293           else{partner = (inext - iPart <= iPart - iprev) ? inext : iprev;}
7294 
7295       if((iPartnerCandidate >= HH_partons.num()) || (iPartnerCandidate < 0)){iPartnerCandidate = -1;}
7296       if((partner >= HH_partons.num()) || (partner < 0)) {partner = -1;}
7297         }
7298 
7299         //by now, a partner *must* have been chosen - unless there's only 1 parton in the event, which is BAD.
7300         //time to fix.
7301         //if somehow everything failed, just skip this parton and put it to its mass shell (here we have to accept the energy conservation violation)
7302         if(partner == -1 && iPartnerCandidate >= 0){
7303       partner = iPartnerCandidate;
7304     } else if(partner == -1 && iPartnerCandidate == -1) {
7305       HHparton parton = HH_partons[iPart];
7306       if(std::abs(parton.id()) < 6 && parton.mass() < pythia.particleData.m0(std::abs(parton.id()))) { // quark case
7307         parton.mass(pythia.particleData.m0(std::abs(parton.id())));
7308         parton.e(std::sqrt(parton.px()*parton.px() + parton.py()*parton.py() + parton.pz()*parton.pz() + parton.mass()*parton.mass()));
7309         HH_partons[iPart] = parton;
7310       } else if(parton.id() == 21 && parton.mass() < 2.*xmq + 0.001) { // gluon case (pythia has m_g = 0.)
7311         parton.mass(2.*xmq + 0.001);
7312         parton.e(std::sqrt(parton.px()*parton.px() + parton.py()*parton.py() + parton.pz()*parton.pz() + parton.mass()*parton.mass()));
7313         HH_partons[iPart] = parton;
7314       }
7315       continue;
7316     }
7317 
7318     //std::cout << "P1_before: " << iPart << ", " << HH_partons[iPart].id() << ", " << HH_partons[iPart].px() << ", " << HH_partons[iPart].py() << ", " << HH_partons[iPart].pz() << ", " << HH_partons[iPart].e() << ", " << HH_partons[iPart].mass() << "\n";
7319     //std::cout << "P2_before: " << partner << ", " << HH_partons[partner].id() << ", " << HH_partons[partner].px() << ", " << HH_partons[partner].py() << ", " << HH_partons[partner].pz() << ", " << HH_partons[partner].e() << ", " << HH_partons[partner].mass() << "\n";
7320 
7321         //Psys
7322         FourVector Psys;
7323         Psys.Set(HH_partons[iPart].px()+HH_partons[partner].px(),HH_partons[iPart].py()+HH_partons[partner].py(),HH_partons[iPart].pz()+HH_partons[partner].pz(),HH_partons[iPart].e()+HH_partons[partner].e());
7324 
7325         //CM velocity
7326         FourVector beta;
7327         beta.Set(Psys.x()/Psys.t(),Psys.y()/Psys.t(),Psys.z()/Psys.t(),0.);
7328         beta.Set(beta.x(),beta.y(),beta.z(),1./(sqrt(1.-(beta.x()*beta.x() + beta.y()*beta.y() + beta.z()*beta.z()))));
7329 
7330         //boosting into CM frame
7331         FourVector p_CM[2]; p_CM[0] = HH_partons[iPart].boost_P(beta); p_CM[1] = HH_partons[partner].boost_P(beta);
7332 
7333         //if E1 + E2 >= m1 + m2, shift momenta
7334         double m2 = 0.;
7335     if ((HH_partons[partner].id() == 21) && (HH_partons[partner].mass() < 2.*xmq + 0.001)){
7336       m2 = 2.*xmq + 0.001;
7337     } else if ((HH_partons[partner].id() == 21) && (HH_partons[partner].mass() >= 2.*xmq + 0.001)){
7338       m2 = HH_partons[partner].mass();
7339     } else if(std::abs(HH_partons[partner].id()) < 3) {
7340       m2 = xmq;
7341     } else if(std::abs(HH_partons[partner].id()) == 3) {
7342       m2 = xms;
7343     } else if(std::abs(HH_partons[partner].id()) == 4) {
7344       m2 = xmc;
7345     } else if(std::abs(HH_partons[partner].id()) == 5) {
7346       m2 = xmb;
7347     }
7348         double Etot = p_CM[0].t() + p_CM[1].t();
7349         if(Etot < m1 + m2 + 0.00001){Etot = m1 + m2 + 0.00001; /*eviol << Etot - (p_CM[0].t() + p_CM[1].t()) << "\n";*/}//can't shift, violating E/P cons.
7350         double E1 = Etot/2. + ((m1*m1)-(m2*m2))/(2.*Etot);
7351         double E2 = Etot/2. - ((m1*m1)-(m2*m2))/(2.*Etot);
7352         double pmag = sqrt(p_CM[0].x()*p_CM[0].x() + p_CM[0].y()*p_CM[0].y() + p_CM[0].z()*p_CM[0].z());
7353         double fac = sqrt(Etot*Etot/4. + ((m1*m1)-(m2*m2))*((m1*m1)-(m2*m2))/(4.*Etot*Etot) - ((m1*m1)+(m2*m2))/2.)/pmag;
7354     //std::cout << "Etot_orig = " << p_CM[0].t() + p_CM[1].t() << " Etot = " << Etot << " pmag = " << pmag << " fac = " << fac << std::endl;
7355 
7356         //rescaling in CM frame
7357     p_CM[0].Set(fac*p_CM[0].x(), fac*p_CM[0].y(), fac*p_CM[0].z(), E1);
7358     p_CM[1].Set(fac*p_CM[1].x(), fac*p_CM[1].y(), fac*p_CM[1].z(), E2);
7359 
7360         //boosting back and setting parton E,P to fixed values
7361     beta.Set(-beta.x(), -beta.y(), -beta.z(), 0.);
7362     beta.Set(beta.x(),beta.y(),beta.z(),1./(sqrt(1.-(beta.x()*beta.x() + beta.y()*beta.y() + beta.z()*beta.z()))));
7363         FourVector p_fin[2]; p_fin[0] = HHboost(beta, p_CM[0]); p_fin[1] = HHboost(beta, p_CM[1]);
7364         HH_partons[iPart].P(p_fin[0]); HH_partons[partner].P(p_fin[1]);
7365     HH_partons[iPart].mass(m1);
7366     HH_partons[partner].mass(m2);
7367 
7368     //std::cout << "P1_after: " << iPart << ", " << HH_partons[iPart].id() << ", " << HH_partons[iPart].px() << ", " << HH_partons[iPart].py() << ", " << HH_partons[iPart].pz() << ", " << HH_partons[iPart].e() << ", " << HH_partons[iPart].mass() << "\n";
7369     //std::cout << "P2_after: " << partner << ", " << HH_partons[partner].id() << ", " << HH_partons[partner].px() << ", " << HH_partons[partner].py() << ", " << HH_partons[partner].pz() << ", " << HH_partons[partner].e() << ", " << HH_partons[partner].mass() << "\n";
7370   }
7371 
7372   //calc. Etot after
7373   /*for(int iPart=0; iPart<HH_partons.num(); ++iPart){Eafter += HH_partons[iPart].e(); pTafter += HH_partons[iPart].pt();}
7374   echg << Eafter-Ebefore << "\n"; ptchg << pTafter-pTbefore << "\n";
7375   eviol.close(); echg.close(); ptchg.close();*/
7376 }
7377