1 //FJSTARTHEADER
2 // $Id: ClusterSequenceStructure.cc 4442 2020-05-05 07:50:11Z soyez $
3 //
4 // Copyright (c) 2005-2020, 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 #include "fastjet/ClusterSequenceStructure.hh"
32 #include "fastjet/Error.hh"
33 #include "fastjet/PseudoJet.hh"
34 #include "fastjet/ClusterSequence.hh"
35 #ifndef __FJCORE__
36 #include "fastjet/ClusterSequenceAreaBase.hh"
37 #endif // __FJCORE__
38 #include <iostream>
39
40 FASTJET_BEGIN_NAMESPACE // defined in fastjet/internal/base.hh
41
42 using namespace std;
43
~ClusterSequenceStructure()44 ClusterSequenceStructure::~ClusterSequenceStructure(){
45 if (_associated_cs != NULL
46 && _associated_cs->will_delete_self_when_unused()) {
47 // automatically handle deletion of the cluster sequence;
48 // execution should only ever reach this point if the user had
49 // called CS::delete_self_when_unused, which resets the count of
50 // the shared pointer to CSS (otherwise the CS's own destructor
51 // will have zeroed the _associated_cs pointer before the shared
52 // pointer count goes to zero [on destruction of the last of the
53 // jets in the CS and the destruction of the CS's copy of the
54 // shared pointer)
55 _associated_cs->signal_imminent_self_deletion();
56 delete _associated_cs;
57 }
58 }
59
60
61 //----------------------------------------------------------------------
62 // Direct access to the associated ClusterSequence object.
63 //----------------------------------------------------------------------
64
65 // check whether this PseudoJet has an associated parent
66 // ClusterSequence
has_valid_cluster_sequence() const67 bool ClusterSequenceStructure::has_valid_cluster_sequence() const{
68 return (_associated_cs != NULL);
69 }
70
71 // get a (const) pointer to the associated ClusterSequence (NULL if
72 // inexistent)
associated_cluster_sequence() const73 const ClusterSequence* ClusterSequenceStructure::associated_cluster_sequence() const{
74 return _associated_cs;
75 }
76
77
78 // If there is a valid cluster sequence associated with this jet,
79 // returns a pointer to it; otherwise throws an Error.
80 //
81 // Open question: should these errors be upgraded to classes of their
82 // own so that they can be caught? [Maybe, but later]
validated_cs() const83 const ClusterSequence * ClusterSequenceStructure::validated_cs() const {
84 if (!_associated_cs)
85 throw Error("you requested information about the internal structure of a jet, but its associated ClusterSequence has gone out of scope.");
86 return _associated_cs;
87 }
88
89
90 //----------------------------------------------------------------------
91 // Methods for access to information about jet structure
92 //----------------------------------------------------------------------
93
94 // check if it has been recombined with another PseudoJet in which
95 // case, return its partner through the argument. Otherwise,
96 // 'partner' is set to 0.
97 //
98 // false is also returned if this PseudoJet has no associated
99 // ClusterSequence
has_partner(const PseudoJet & reference,PseudoJet & partner) const100 bool ClusterSequenceStructure::has_partner(const PseudoJet &reference, PseudoJet &partner) const{
101 return validated_cs()->has_partner(reference, partner);
102 }
103
104 // check if it has been recombined with another PseudoJet in which
105 // case, return its child through the argument. Otherwise, 'child'
106 // is set to 0.
107 //
108 // false is also returned if this PseudoJet has no associated
109 // ClusterSequence, with the child set to 0
has_child(const PseudoJet & reference,PseudoJet & child) const110 bool ClusterSequenceStructure::has_child(const PseudoJet &reference, PseudoJet &child) const{
111 return validated_cs()->has_child(reference, child);
112 }
113
114 // check if it is the product of a recombination, in which case
115 // return the 2 parents through the 'parent1' and 'parent2'
116 // arguments. Otherwise, set these to 0.
117 //
118 // false is also returned if this PseudoJet has no parent
119 // ClusterSequence
has_parents(const PseudoJet & reference,PseudoJet & parent1,PseudoJet & parent2) const120 bool ClusterSequenceStructure::has_parents(const PseudoJet &reference, PseudoJet &parent1, PseudoJet &parent2) const{
121 return validated_cs()->has_parents(reference, parent1, parent2);
122 }
123
124
125 // check if the reference PseudoJet is inside the "jet" passed as an argument
126 //
127 // an error is thrown if there is no CS associated with one of the 2 jets.
128 // fasle is returned if teh 2 jets do not belong to the same CS
object_in_jet(const PseudoJet & reference,const PseudoJet & jet) const129 bool ClusterSequenceStructure::object_in_jet(const PseudoJet &reference, const PseudoJet &jet) const{
130 if ((!has_associated_cluster_sequence()) || (!jet.has_associated_cluster_sequence()))
131 throw Error("you requested information about the internal structure of a jet, but it is not associated with a ClusterSequence or its associated ClusterSequence has gone out of scope.");
132
133 if (reference.associated_cluster_sequence() != jet.associated_cluster_sequence()) return false;
134
135 return validated_cs()->object_in_jet(reference, jet);
136 }
137
138
139 // return true if the structure supports constituents.
140 //
141 // an Error is thrown if this PseudoJet has no currently valid
142 // associated ClusterSequence
has_constituents() const143 bool ClusterSequenceStructure::has_constituents() const{
144 if (!has_associated_cluster_sequence())
145 throw Error("you requested information about the internal structure of a jet, but it is not associated with a ClusterSequence or its associated ClusterSequence has gone out of scope.");
146
147 return true;
148 }
149
150
151 // retrieve the constituents. An empty vector is returned if there is
152 // no associated ClusterSequence
constituents(const PseudoJet & reference) const153 vector<PseudoJet> ClusterSequenceStructure::constituents(const PseudoJet &reference) const{
154 return validated_cs()->constituents(reference);
155 }
156
157 // return true if the structure supports exclusive_subjets.
158 //
159 // an Error is thrown if this PseudoJet has no currently valid
160 // associated ClusterSequence
has_exclusive_subjets() const161 bool ClusterSequenceStructure::has_exclusive_subjets() const{
162 if (!has_associated_cluster_sequence())
163 throw Error("you requested information about the internal structure of a jet, but it is not associated with a ClusterSequence or its associated ClusterSequence has gone out of scope.");
164
165 return true;
166 }
167
168 // return a vector of all subjets of the current jet (in the sense
169 // of the exclusive algorithm) that would be obtained when running
170 // the algorithm with the given dcut.
171 //
172 // Time taken is O(m ln m), where m is the number of subjets that
173 // are found. If m gets to be of order of the total number of
174 // constituents in the jet, this could be substantially slower than
175 // just getting that list of constituents.
176 //
177 // an Error is thrown if this PseudoJet has no currently valid
178 // associated ClusterSequence
exclusive_subjets(const PseudoJet & reference,const double & dcut) const179 std::vector<PseudoJet> ClusterSequenceStructure::exclusive_subjets (const PseudoJet &reference, const double & dcut) const {
180 return validated_cs()->exclusive_subjets(reference, dcut);
181 }
182
183 // return the size of exclusive_subjets(...); still n ln n with same
184 // coefficient, but marginally more efficient than manually taking
185 // exclusive_subjets.size()
186 //
187 // an Error is thrown if this PseudoJet has no currently valid
188 // associated ClusterSequence
n_exclusive_subjets(const PseudoJet & reference,const double & dcut) const189 int ClusterSequenceStructure::n_exclusive_subjets(const PseudoJet &reference, const double & dcut) const {
190 return validated_cs()->n_exclusive_subjets(reference, dcut);
191 }
192
193 // return the list of subjets obtained by unclustering the supplied
194 // jet down to n subjets (or all constituents if there are fewer
195 // than n).
196 //
197 // requires n ln n time
198 //
199 // an Error is thrown if this PseudoJet has no currently valid
200 // associated ClusterSequence
exclusive_subjets_up_to(const PseudoJet & reference,int nsub) const201 std::vector<PseudoJet> ClusterSequenceStructure::exclusive_subjets_up_to (const PseudoJet &reference, int nsub) const {
202 return validated_cs()->exclusive_subjets_up_to(reference, nsub);
203 }
204
205 // return the dij that was present in the merging nsub+1 -> nsub
206 // subjets inside this jet.
207 //
208 // an Error is thrown if this PseudoJet has no currently valid
209 // associated ClusterSequence
exclusive_subdmerge(const PseudoJet & reference,int nsub) const210 double ClusterSequenceStructure::exclusive_subdmerge(const PseudoJet &reference, int nsub) const {
211 return validated_cs()->exclusive_subdmerge(reference, nsub);
212 }
213
214 // return the maximum dij that occurred in the whole event at the
215 // stage that the nsub+1 -> nsub merge of subjets occurred inside
216 // this jet.
217 //
218 // an Error is thrown if this PseudoJet has no currently valid
219 // associated ClusterSequence
exclusive_subdmerge_max(const PseudoJet & reference,int nsub) const220 double ClusterSequenceStructure::exclusive_subdmerge_max(const PseudoJet &reference, int nsub) const {
221 return validated_cs()->exclusive_subdmerge_max(reference, nsub);
222 }
223
224
225 //----------------------------------------------------------------------
226 // information related to the pieces of the jet
227 //----------------------------------------------------------------------
228
229 // by convention, a jet associated with a ClusterSequence will have
230 // pieces if it has parents in the cluster sequence.
231 //
232 // an error is thrown if the ClusterSequence is out of scope (since
233 // the answer depends on information in the Cluster Sequence)
has_pieces(const PseudoJet & reference) const234 bool ClusterSequenceStructure::has_pieces(const PseudoJet &reference) const{
235 PseudoJet dummy1, dummy2;
236 return has_parents(reference, dummy1, dummy2);
237 }
238
239 // by convention, the pieces of a jet associated with a
240 // ClusterSequence are its parents in the Cluster Sequence. If it has
241 // no parents, an empty jet is returned.
242 //
243 // an error is thrown if the ClusterSequence is out of scope
pieces(const PseudoJet & reference) const244 vector<PseudoJet> ClusterSequenceStructure::pieces(const PseudoJet &reference) const{
245 PseudoJet j1, j2;
246 vector<PseudoJet> res;
247 if (has_parents(reference, j1, j2)){
248 res.push_back(j1);
249 res.push_back(j2);
250 }
251
252 return res;
253 }
254
255
256 //----------------------------------------------------------------------
257 // the following ones require a computation of the area in the
258 // associated ClusterSequence (See ClusterSequenceAreaBase for details)
259 //----------------------------------------------------------------------
260
261 #ifndef __FJCORE__
262 // if possible, return a valid ClusterSequenceAreaBase pointer; otherwise
263 // throw an error
validated_csab() const264 const ClusterSequenceAreaBase * ClusterSequenceStructure::validated_csab() const {
265 const ClusterSequenceAreaBase *csab = dynamic_cast<const ClusterSequenceAreaBase*>(validated_cs());
266 if (csab == NULL) throw Error("you requested jet-area related information, but the PseudoJet does not have associated area information.");
267 return csab;
268 }
269
270 // check if it has a defined area
has_area() const271 bool ClusterSequenceStructure::has_area() const{
272 if (! has_associated_cluster_sequence()) return false;
273 return (dynamic_cast<const ClusterSequenceAreaBase*>(_associated_cs) != NULL);
274 }
275
276 // return the jet (scalar) area.
277 // throw an Error if there is no support for area in the associated CS
area(const PseudoJet & reference) const278 double ClusterSequenceStructure::area(const PseudoJet &reference) const{
279 return validated_csab()->area(reference);
280 }
281
282 // return the error (uncertainty) associated with the determination
283 // of the area of this jet.
284 // throws an Error if there is no support for area in the associated CS
area_error(const PseudoJet & reference) const285 double ClusterSequenceStructure::area_error(const PseudoJet &reference) const{
286 return validated_csab()->area_error(reference);
287 }
288
289 // return the jet 4-vector area
290 // throws an Error if there is no support for area in the associated CS
area_4vector(const PseudoJet & reference) const291 PseudoJet ClusterSequenceStructure::area_4vector(const PseudoJet &reference) const{
292 return validated_csab()->area_4vector(reference);
293 }
294
295 // true if this jet is made exclusively of ghosts
296 // throws an Error if there is no support for area in the associated CS
is_pure_ghost(const PseudoJet & reference) const297 bool ClusterSequenceStructure::is_pure_ghost(const PseudoJet &reference) const{
298 return validated_csab()->is_pure_ghost(reference);
299 }
300
301 #endif // __FJCORE__
302
303
304
305 FASTJET_END_NAMESPACE
306