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