To continue, I mangled the resonanceBuilder to become something like this:
massBuilder::massBuilder(float arg_resonance_mass, float arg_recoil_mass, float arg_chi2_recoil_frac, float arg_ecm, bool arg_use_MC_Kinematics){resonance_mass = arg_resonance_mass, recoil_mass = arg_recoil_mass, chi2_recoil_frac = arg_c
hi2_recoil_frac, ecm = arg_ecm, arg_use_MC_Kinematics = arg_use_MC_Kinematics;}
ROOT::VecOps::RVecedm4hep::ReconstructedParticleData massBuilder::massBuilder::operator()(ROOT::VecOps::RVecedm4hep::ReconstructedParticleData legs, ROOT::VecOps::RVec recind, ROOT::VecOps::RVec mcind, ROOT::VecOps::RVec<ed
m4hep::ReconstructedParticleData> reco, ROOT::VecOps::RVecedm4hep::MCParticleData mc, ROOT::VecOps::RVec parents, ROOT::VecOps::RVec daugthers) {
ROOT::VecOps::RVec<edm4hep::ReconstructedParticleData> result;
result.reserve(3);
std::vector<std::vector<int>> pairs; // for each permutation, add the indices of the muons \
int n = legs.size();
if(n > 1) {
ROOT::VecOps::RVec<bool> v(n);
std::fill(v.end() - 2, v.end(), true); // helper variable for permutations \
do {
std::vector<int> pair;
edm4hep::ReconstructedParticleData reso;
reso.charge = 0;
TLorentzVector reso_lv;
for(int i = 0; i < n; ++i) {
if(v[i]) {
pair.push_back(i);
reso.charge += legs[i].charge;
TLorentzVector leg_lv;
if(use_mc_kinematics) { // MC kinematics
int track_index = legs[i].tracks_begin; // index in the Track array \
int mc_index = ReconstructedParticle2MC::getTrack2MC_index(track_index, recind, mcind, reco);
if (mc_index >= 0 && mc_index < mc.size()) {
leg_lv.SetXYZM(mc.at(mc_index).momentum.x, mc.at(mc_index).momentum.y, mc.at(mc_index).momentum.z, mc.at(mc_index).mass);
}
}
else { // reco kinematics \
leg_lv.SetXYZM(legs[i].momentum.x, legs[i].momentum.y, legs[i].momentum.z, legs[i].mass);
}
reso_lv += leg_lv;
}
}
if(reso.charge != 0) continue; // neglect non-zero charge pairs \
reso.momentum.x = reso_lv.Px();
reso.momentum.y = reso_lv.Py();
reso.momentum.z = reso_lv.Pz();
reso.mass = reso_lv.M();
result.emplace_back(reso);
pairs.push_back(pair);
} while(std::next_permutation(v.begin(), v.end()));
}
else {
std::cout << “ERROR: resonanceBuilder_mass_recoil, at least two leptons required.” << std::endl;
exit(1);
}
if(result.size() > 1) {
ROOT::VecOps::RVec<edm4hep::ReconstructedParticleData> bestReso;
int idx_min = -1;
float mass_min = 9e9;
for (int i = 0; i < result.size(); ++i) { \
TLorentzVector tg;
tg.SetXYZM(result.at(i).momentum.x, result.at(i).momentum.y, result.at(i).momentum.z, result.at(i).mass);
float boost = tg.P();
float mass = (result.at(i).mass - resonance_mass); // mass
if(mass < mass_min) {
mass_min = mass;
idx_min = i;
}
}
if(idx_min > -1) {
bestReso.push_back(result.at(idx_min));
auto & l1 = legs[pairs[idx_min][0]];
auto & l2 = legs[pairs[idx_min][1]];
bestReso.emplace_back(l1);
bestReso.emplace_back(l2);
}
else {
std::cout << “ERROR: resonanceBuilder_mass_recoil, no mininum found.” << std::endl;
exit(1);
}
return bestReso;
}
else {
auto & l1 = legs[0];
auto & l2 = legs[1];
result.emplace_back(l1);
result.emplace_back(l2);
return result;
}
}
I really was thinking it would be something like taking the recoil calculations and changing the definitions of d and d_min where i replaced with mass but it seems it would be more involved than that.
Thanks again,
Hayden Shaddix