FastJet 3.4.1
JadePlugin.cc
1//FJSTARTHEADER
2// $Id$
3//
4// Copyright (c) 2007-2023, Matteo Cacciari, Gavin P. Salam and Gregory Soyez
5//
6//----------------------------------------------------------------------
7// This file is part of FastJet.
8//
9// FastJet is free software; you can redistribute it and/or modify
10// it under the terms of the GNU General Public License as published by
11// the Free Software Foundation; either version 2 of the License, or
12// (at your option) any later version.
13//
14// The algorithms that underlie FastJet have required considerable
15// development. They are described in the original FastJet paper,
16// hep-ph/0512210 and in the manual, arXiv:1111.6097. If you use
17// FastJet as part of work towards a scientific publication, please
18// quote the version you use and include a citation to the manual and
19// optionally also to hep-ph/0512210.
20//
21// FastJet is distributed in the hope that it will be useful,
22// but WITHOUT ANY WARRANTY; without even the implied warranty of
23// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24// GNU General Public License for more details.
25//
26// You should have received a copy of the GNU General Public License
27// along with FastJet. If not, see <http://www.gnu.org/licenses/>.
28//----------------------------------------------------------------------
29//FJENDHEADER
30
31// fastjet stuff
32#include "fastjet/ClusterSequence.hh"
33#include "fastjet/JadePlugin.hh"
34#include <iostream>
35//#include "fastjet/internal/ClusterSequence_N2.icc"
36#include "fastjet/NNH.hh"
37#include "fastjet/NNFJN2Plain.hh"
38
39// other stuff
40#include <vector>
41#include <sstream>
42#include <limits>
43
44
45
46
47using namespace std;
48
49FASTJET_BEGIN_NAMESPACE // defined in fastjet/internal/base.hh
50
51
52//----------------------------------------------------------------------
53/// class to help run a JADE algorithm
54///
55/// This class works both with NNH and NNFJN2Plain clustering
56/// helpers. They both use the same init(...) call, but for the
57/// clustering:
58///
59/// - NNH uses distance(...) and beam_distance()
60/// - NNFJPlainN2 uses geometrical_distance(...), momentum_factor()
61/// and geometrical_beam_distance()
62///
63/// For NNFJPlainN2 the 2 E_i E_j (1-cos theta_{ij}) factor
64/// gets broken up into
65///
66/// sqrt(2)*min(E_i,E_j) * [sqrt(2)*max(E_i,E_j) (1 - cos \theta_{ij})]
67///
68/// The second factor is what we call the "geometrical_distance" even
69/// though it isn't actually purely geometrical. But the fact that it
70/// gets multiplied by min(E_i,E_j) to get the full distance is
71/// sufficient for the validity of the FJ lemma, allowing for the use
72/// of NNFJN2Plain.
73class JadeBriefJet {
74public:
75 void init(const PseudoJet & jet) {
76 double norm = 1.0/sqrt(jet.modp2());
77 nx = jet.px() * norm;
78 ny = jet.py() * norm;
79 nz = jet.pz() * norm;
80 rt2E = sqrt(2.0)*jet.E();
81 }
82
83 double distance(const JadeBriefJet * jet) const {
84 double dij = 1 - nx*jet->nx
85 - ny*jet->ny
86 - nz*jet->nz;
87 dij *= rt2E*jet->rt2E;
88 return dij;
89 }
90
91 double geometrical_distance(const JadeBriefJet * jet) const {
92 double dij = 1 - nx*jet->nx
93 - ny*jet->ny
94 - nz*jet->nz;
95 dij *= max(rt2E,jet->rt2E);
96 return dij;
97 }
98
99 double momentum_factor() const {
100 return rt2E;
101 }
102
103 double beam_distance() const {
104 return numeric_limits<double>::max();
105 }
106
107 double geometrical_beam_distance() const {
108 // get a number that is almost the same as max(), just a little
109 // smaller so as to ensure that when we divide it by rt2E and then
110 // multiply it again, we won't get an overflow.
111 // Watch out for cases where rt2E < 1.0 (cf. bug fix from
112 // andrii.verbytskyi@mpp.mpg.de on 2019-02-14)
113 const double almost_max = numeric_limits<double>::max() * (1 - 1e-13);
114 if (rt2E>1.0) return almost_max / rt2E;
115 else return almost_max;
116 }
117
118private:
119 double rt2E, nx, ny, nz;
120};
121
122
123//----------------------------------------------------------------------
124string JadePlugin::description () const {
125 ostringstream desc;
126 desc << "e+e- JADE algorithm plugin";
127 switch(_strategy) {
128 case strategy_NNH:
129 desc << ", using NNH strategy"; break;
130 case strategy_NNFJN2Plain:
131 desc << ", using NNFJN2Plain strategy"; break;
132 default:
133 throw Error("Unrecognized strategy in JadePlugin");
134 }
135
136 return desc.str();
137}
138
139// //----------------------------------------------------------------------
140// void JadePlugin::run_clustering(ClusterSequence & cs) const {
141// int njets = cs.jets().size();
142//
143// //SharedPtr<NNBase<> > nn;
144// NNBase<> * nn;
145// switch(_strategy) {
146// case strategy_NNH:
147// //nn.reset(new NNH<JadeBriefJet>(cs.jets()));
148// nn = new NNH<JadeBriefJet>(cs.jets());
149// break;
150// case strategy_NNFJN2Plain:
151// //nn.reset(new NNFJN2Plain<JadeBriefJet>(cs.jets()));
152// nn = new NNFJN2Plain<JadeBriefJet>(cs.jets());
153// break;
154// default:
155// throw Error("Unrecognized strategy in JadePlugin");
156// }
157// //NNH<JadeBriefJet> nnh(cs.jets());
158// //NNFJN2Plain<JadeBriefJet> nnh(cs.jets());
159//
160// // if testing against Hoeth's implementation, need to rescale the
161// // dij by Q^2.
162// //double Q2 = cs.Q2();
163//
164// while (njets > 0) {
165// int i, j, k;
166// double dij = nn->dij_min(i, j);
167//
168// if (j >= 0) {
169// cs.plugin_record_ij_recombination(i, j, dij, k);
170// nn->merge_jets(i, j, cs.jets()[k], k);
171// } else {
172// double diB = cs.jets()[i].E()*cs.jets()[i].E(); // get new diB
173// cs.plugin_record_iB_recombination(i, diB);
174// nn->remove_jet(i);
175// }
176// njets--;
177// }
178// delete nn;
179// }
180
181
182template<class N> void JadePlugin::_actual_run_clustering(ClusterSequence & cs) const {
183
184 int njets = cs.jets().size();
185
186 N nn(cs.jets());
187
188 // if testing against Hoeth's implementation, need to rescale the
189 // dij by Q^2.
190 //double Q2 = cs.Q2();
191
192 while (njets > 0) {
193 int i, j, k;
194 double dij = nn.dij_min(i, j);
195
196 if (j >= 0) {
197 cs.plugin_record_ij_recombination(i, j, dij, k);
198 nn.merge_jets(i, j, cs.jets()[k], k);
199 } else {
200 double diB = cs.jets()[i].E()*cs.jets()[i].E(); // get new diB
202 nn.remove_jet(i);
203 }
204 njets--;
205 }
206
207}
208
209//----------------------------------------------------------------------
210void JadePlugin::run_clustering(ClusterSequence & cs) const {
211
212 switch(_strategy) {
213 case strategy_NNH:
214 _actual_run_clustering<NNH<JadeBriefJet> >(cs);
215 break;
216 case strategy_NNFJN2Plain:
217 _actual_run_clustering<NNFJN2Plain<JadeBriefJet> >(cs);
218 break;
219 default:
220 throw Error("Unrecognized strategy in JadePlugin");
221 }
222}
223
224
225FASTJET_END_NAMESPACE // defined in fastjet/internal/base.hh
deals with clustering
void plugin_record_iB_recombination(int jet_i, double diB)
record the fact that there has been a recombination between jets()[jet_i] and the beam,...
const std::vector< PseudoJet > & jets() const
allow the user to access the internally stored _jets() array, which contains both the initial particl...
void plugin_record_ij_recombination(int jet_i, int jet_j, double dij, int &newjet_k)
record the fact that there has been a recombination between jets()[jet_i] and jets()[jet_k],...
base class corresponding to errors that can be thrown by FastJet
Definition: Error.hh:52
double norm(const VPoint p)
norm of a vector
Definition: Voronoi.hh:155