File indexing completed on 2026-09-14 09:06:59
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023 #ifndef __FASTJET_CONTRIB_RECURSIVELUNDEEGENERATOR_HH__
0024 #define __FASTJET_CONTRIB_RECURSIVELUNDEEGENERATOR_HH__
0025
0026 #include "fastjet/contrib/LundEEHelpers.hh"
0027
0028 #include <fastjet/internal/base.hh>
0029 #include "fastjet/tools/Recluster.hh"
0030 #include "fastjet/JetDefinition.hh"
0031 #include "fastjet/PseudoJet.hh"
0032 #include <string>
0033 #include <vector>
0034 #include <utility>
0035 #include <queue>
0036
0037 using namespace std;
0038
0039 FASTJET_BEGIN_NAMESPACE
0040
0041 namespace contrib{
0042
0043
0044
0045
0046
0047 class LundEEDeclustering {
0048 public:
0049
0050
0051 const PseudoJet & pair() const {return pair_;}
0052
0053 const PseudoJet & harder() const {return harder_;}
0054
0055 const PseudoJet & softer() const {return softer_;}
0056
0057
0058
0059 double m() const {return m_;}
0060
0061
0062 double eta() const {return eta_;}
0063
0064
0065 double sin_theta() const {return sin_theta_;}
0066
0067
0068 double z() const {return z_;}
0069
0070
0071 double kt() const {return kt_;}
0072
0073
0074 double lnkt() const {return lnkt_;}
0075
0076
0077 double kappa() const {return kappa_;}
0078
0079
0080 int iplane() const {return iplane_;}
0081
0082
0083
0084 int depth() const {return depth_;}
0085
0086
0087
0088
0089 int leaf_iplane() const {return leaf_iplane_;}
0090
0091
0092 int sign_s() const {return sign_s_;}
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112 double psibar() const {return psibar_;}
0113
0114
0115
0116
0117
0118 double psi() const {return psi_;}
0119
0120
0121 void set_psi(double psi) {psi_ = psi;}
0122
0123
0124
0125 std::pair<double,double> const lund_coordinates() const {
0126 return std::pair<double,double>(eta_,lnkt_);
0127 }
0128
0129 virtual ~LundEEDeclustering() {}
0130
0131 private:
0132 int iplane_;
0133 double psi_, psibar_, lnkt_, eta_;
0134 double m_, z_, kt_, kappa_, sin_theta_;
0135 PseudoJet pair_, harder_, softer_;
0136 int depth_ = -1, leaf_iplane_ = -1;
0137 int sign_s_;
0138
0139 protected:
0140
0141
0142
0143 LundEEDeclustering() {}
0144
0145
0146
0147 LundEEDeclustering(const PseudoJet& pair,
0148 const PseudoJet& j1, const PseudoJet& j2,
0149 int iplane = -1, double psi = 0.0, double psibar = 0.0, int depth = -1, int leaf_iplane = -1, int sign_s = 1);
0150
0151 friend class RecursiveLundEEGenerator;
0152
0153 };
0154
0155
0156
0157
0158 inline bool operator<(const LundEEDeclustering& d1, const LundEEDeclustering& d2) {
0159 return d1.kt() < d2.kt();
0160 }
0161
0162
0163
0164
0165
0166 class RecursiveLundEEGenerator {
0167 public:
0168
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186
0187
0188 RecursiveLundEEGenerator(int max_depth = 0, bool dynamical_psi_ref = false) :
0189 max_depth_(max_depth), nx_(1,0,0,0), ny_(0,1,0,0), dynamical_psi_ref_(dynamical_psi_ref)
0190 {}
0191
0192
0193 virtual ~RecursiveLundEEGenerator() {}
0194
0195
0196
0197
0198
0199
0200 virtual std::vector<LundEEDeclustering> result(const ClusterSequence & cs) const {
0201 std::vector<PseudoJet> exclusive_jets = cs.exclusive_jets(2);
0202 assert(exclusive_jets.size() == 2);
0203
0204
0205 if (exclusive_jets[0].pz() < exclusive_jets[1].pz()) {
0206 std::swap(exclusive_jets[0],exclusive_jets[1]);
0207 }
0208
0209 PseudoJet d_ev = exclusive_jets[0] - exclusive_jets[1];
0210 lund_plane::Matrix3 rotmat = lund_plane::Matrix3::from_direction(d_ev);
0211
0212 std::vector<LundEEDeclustering> declusterings;
0213 int depth = 0;
0214 int max_iplane_sofar = 1;
0215
0216
0217
0218
0219 #define RLEEG_NEWPSIBAR
0220 #ifdef RLEEG_NEWPSIBAR
0221
0222 PseudoJet ref_plane;
0223 double last_psibar = 0.;
0224 bool first_time = true;
0225
0226 for (unsigned ijet = 0; ijet < exclusive_jets.size(); ijet++) {
0227 int sign_s = ijet == 0? +1 : -1;
0228 append_to_vector(declusterings, exclusive_jets[ijet], depth, ijet, max_iplane_sofar,
0229 rotmat, sign_s, ref_plane, last_psibar, first_time);
0230 }
0231 #else
0232 for (unsigned ijet = 0; ijet < exclusive_jets.size(); ijet++) {
0233
0234
0235 PseudoJet axis = d_ev/sqrt(d_ev.modp2());
0236 PseudoJet ref_plane = axis;
0237
0238 int sign_s = ijet == 0? +1 : -1;
0239 bool
0240
0241 append_to_vector(declusterings, exclusive_jets[ijet], depth, ijet, max_iplane_sofar,
0242 rotmat, sign_s, ref_plane, 0., true);
0243 }
0244 #endif
0245
0246
0247 typedef LundEEDeclustering LD;
0248
0249
0250
0251 sort(declusterings.begin(), declusterings.end(),
0252 [](const LD & d1, const LD & d2){return d1.kt() > d2.kt();});
0253
0254 return declusterings;
0255 }
0256
0257 private:
0258
0259
0260
0261
0262
0263 void append_to_vector(std::vector<LundEEDeclustering> & declusterings,
0264 const PseudoJet & jet, int depth,
0265 int iplane, int & max_iplane_sofar,
0266 const lund_plane::Matrix3 & rotmat, int sign_s,
0267 PseudoJet & psibar_ref_plane,
0268 const double & last_psibar, bool & first_time) const {
0269 PseudoJet j1, j2;
0270 if (!jet.has_parents(j1, j2)) return;
0271 if (j1.modp2() < j2.modp2()) std::swap(j1,j2);
0272
0273
0274 lund_plane::Matrix3 new_rotmat;
0275 if (dynamical_psi_ref_) {
0276 new_rotmat = lund_plane::Matrix3::from_direction(rotmat.transpose()*(sign_s*jet)) * rotmat;
0277 } else {
0278 new_rotmat = rotmat;
0279 }
0280 PseudoJet rx = new_rotmat * nx_;
0281 PseudoJet ry = new_rotmat * ny_;
0282 PseudoJet u1 = j1/j1.modp(), u2 = j2/j2.modp();
0283 PseudoJet du = u2 - u1;
0284 double x = du.px() * rx.px() + du.py() * rx.py() + du.pz() * rx.pz();
0285 double y = du.px() * ry.px() + du.py() * ry.py() + du.pz() * ry.pz();
0286 double psi = atan2(y,x);
0287
0288
0289 double psibar = 0.;
0290 PseudoJet n1, n2;
0291
0292
0293 if (first_time) {
0294
0295 #ifdef RLEEG_NEWPSIBAR
0296
0297
0298 assert(last_psibar == 0.0);
0299 psibar = 0.0;
0300 n2 = lund_plane::cross_product(j1,j2);
0301 n2 /= n2.modp();
0302 psibar_ref_plane = n2;
0303 first_time = false;
0304 #else
0305
0306 n1 = lund_plane::cross_product(psibar_ref_plane,j1);
0307 n2 = lund_plane::cross_product(j1,j2);
0308
0309 double signed_angle = 0.;
0310 n2 /= n2.modp();
0311 if (n1.modp() != 0) {
0312 n1 /= n1.modp();
0313 signed_angle = lund_plane::signed_angle_between_planes(n1,n2,j1);
0314 }
0315
0316 psibar = lund_plane::map_to_pi(j1.phi() + signed_angle);
0317 #endif
0318 }
0319
0320
0321
0322 else {
0323 n2 = lund_plane::cross_product(j1,j2);
0324 n2 /= n2.modp();
0325 psibar = lund_plane::map_to_pi(last_psibar + sign_s*lund_plane::signed_angle_between_planes(psibar_ref_plane, n2, j1));
0326 }
0327
0328 int leaf_iplane = -1;
0329
0330
0331 bool recurse_into_softer = (depth < max_depth_ || max_depth_ < 0);
0332 if (recurse_into_softer) {
0333 max_iplane_sofar += 1;
0334 leaf_iplane = max_iplane_sofar;
0335 }
0336
0337 LundEEDeclustering declust(jet, j1, j2, iplane, psi, psibar, depth, leaf_iplane, sign_s);
0338 declusterings.push_back(declust);
0339
0340
0341
0342
0343 bool lcl_first_time = false;
0344 append_to_vector(declusterings, j1, depth, iplane, max_iplane_sofar, new_rotmat, sign_s, n2, psibar, lcl_first_time);
0345 if (recurse_into_softer) {
0346 append_to_vector(declusterings, j2, depth+1, leaf_iplane, max_iplane_sofar, new_rotmat, sign_s, n2, psibar, lcl_first_time);
0347 }
0348 }
0349
0350 int max_depth_ = 0;
0351
0352 PseudoJet nx_;
0353 PseudoJet ny_;
0354 bool dynamical_psi_ref_;
0355 };
0356
0357 }
0358
0359 FASTJET_END_NAMESPACE
0360
0361
0362 std::ostream & operator<<(std::ostream & ostr, const fastjet::contrib::LundEEDeclustering & d);
0363
0364 #endif