Fork me on GitHub

source: svn/trunk/Utilities/Fastjet/src/ClusterSequence_CP2DChan.cc@ 11

Last change on this file since 11 was 11, checked in by severine ovyn, 16 years ago

Fastjet added; CDFCones directory has been changed

File size: 11.6 KB
Line 
1//STARTHEADER
2// $Id: ClusterSequence_CP2DChan.cc,v 1.1 2008-11-06 14:32:14 ovyn Exp $
3//
4// Copyright (c) 2005-2006, Matteo Cacciari and Gavin Salam
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 and are described in hep-ph/0512210. If you use
16// FastJet as part of work towards a scientific publication, please
17// include a citation to the FastJet paper.
18//
19// FastJet is distributed in the hope that it will be useful,
20// but WITHOUT ANY WARRANTY; without even the implied warranty of
21// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22// GNU General Public License for more details.
23//
24// You should have received a copy of the GNU General Public License
25// along with FastJet; if not, write to the Free Software
26// Foundation, Inc.:
27// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28//----------------------------------------------------------------------
29//ENDHEADER
30
31#include "../include/fastjet/ClusterSequence.hh"
32#include "../include/fastjet/internal/ClosestPair2D.hh"
33#include<limits>
34#include<vector>
35#include<cmath>
36#include<iostream>
37
38FASTJET_BEGIN_NAMESPACE // defined in fastjet/internal/base.hh
39
40using namespace std;
41
42// place for things we don't want outside world to run into
43namespace Private {
44 /// class for helping us deal with mirror-image particles.
45 class MirrorInfo{
46 public:
47 int orig, mirror;
48 MirrorInfo(int a, int b) : orig(a), mirror(b) {};
49 MirrorInfo() {};
50 };
51
52 /// if there is a need for a mirror when looking for closest pairs
53 /// up to distance D, then return true and turn the supplied point
54 /// into its mirror copy
55 bool make_mirror(Coord2D & point, double Dlim) {
56 if (point.y < Dlim) {point.y += twopi; return true;}
57 if (twopi-point.y < Dlim) {point.y -= twopi; return true;}
58 return false;
59 }
60
61}
62
63using namespace Private;
64
65
66//----------------------------------------------------------------------
67/// clusters only up to a distance Dlim -- does not deal with "inclusive" jets
68/// -- these are left to some other part of the program
69void ClusterSequence::_CP2DChan_limited_cluster (double Dlim) {
70
71 unsigned int n = _initial_n;
72
73 vector<MirrorInfo> coordIDs(2*n); // coord IDs of a given jetID
74 vector<int> jetIDs(2*n); // jet ID for a given coord ID
75 vector<Coord2D> coords(2*n); // our coordinates (and copies)
76
77 // start things off...
78 double minrap = numeric_limits<double>::max();
79 double maxrap = -minrap;
80 int coord_index = -1;
81 int n_active = 0;
82 for (unsigned jet_i = 0; jet_i < _jets.size(); jet_i++) {
83
84 // skip jets that already have children or that have infinite
85 // rapidity
86 if (_history[_jets[jet_i].cluster_hist_index()].child != Invalid ||
87 (_jets[jet_i].E() == abs(_jets[jet_i].pz()) &&
88 _jets[jet_i].perp2() == 0.0)
89 ) {continue;}
90
91 n_active++;
92
93 coordIDs[jet_i].orig = ++coord_index;
94 coords[coord_index] = Coord2D(_jets[jet_i].rap(), _jets[jet_i].phi_02pi());
95 jetIDs[coord_index] = jet_i;
96 minrap = min(coords[coord_index].x,minrap);
97 maxrap = max(coords[coord_index].x,maxrap);
98
99 Coord2D mirror_point(coords[coord_index]);
100 if (make_mirror(mirror_point, Dlim)) {
101 coordIDs[jet_i].mirror = ++coord_index;
102 coords[coord_index] = mirror_point;
103 jetIDs[coord_index] = jet_i;
104 } else {
105 coordIDs[jet_i].mirror = Invalid;
106 }
107 }
108
109 // set them to their actual size...
110 coords.resize(coord_index+1);
111
112 // establish limits (with some leeway on rapidity)
113 Coord2D left_edge(minrap-1.0, -pi);
114 Coord2D right_edge(maxrap+1.0, 3*pi);
115
116 //cerr << "minrap, maxrap = " << minrap << " " << maxrap << endl;
117
118 // now create the closest pair search object
119 ClosestPair2D cp(coords, left_edge, right_edge);
120
121 // cross check to see what's going on...
122 //cerr << "Tree depths before: ";
123 //cp.print_tree_depths(cerr);
124
125 // and start iterating...
126 vector<Coord2D> new_points(2);
127 vector<unsigned int> cIDs_to_remove(4);
128 vector<unsigned int> new_cIDs(2);
129
130 do {
131 // find out which pair we recombine
132 unsigned int cID1, cID2;
133 double distance2;
134 cp.closest_pair(cID1,cID2,distance2);
135
136 // if the closest distance > Dlim, we exit and go to "inclusive" stage
137 if (distance2 > Dlim*Dlim) {break;}
138
139 // normalise distance as we like it
140 distance2 *= _invR2;
141
142 // do the recombination...
143 int jet_i = jetIDs[cID1];
144 int jet_j = jetIDs[cID2];
145 int newjet_k;
146 _do_ij_recombination_step(jet_i, jet_j, distance2, newjet_k);
147
148 // don't bother with any further action if only one active particle
149 // is left (also avoid closest-pair error [cannot remove last particle]).
150 if (--n_active == 1) {break;}
151
152 // now prepare operations on CP structure
153 cIDs_to_remove.resize(0);
154 cIDs_to_remove.push_back(coordIDs[jet_i].orig);
155 cIDs_to_remove.push_back(coordIDs[jet_j].orig);
156 if (coordIDs[jet_i].mirror != Invalid)
157 cIDs_to_remove.push_back(coordIDs[jet_i].mirror);
158 if (coordIDs[jet_j].mirror != Invalid)
159 cIDs_to_remove.push_back(coordIDs[jet_j].mirror);
160
161 Coord2D new_point(_jets[newjet_k].rap(),_jets[newjet_k].phi_02pi());
162 new_points.resize(0);
163 new_points.push_back(new_point);
164 if (make_mirror(new_point, Dlim)) new_points.push_back(new_point);
165
166 // carry out actions on search tree
167 cp.replace_many(cIDs_to_remove, new_points, new_cIDs);
168
169 // now fill in info for new points...
170 coordIDs[newjet_k].orig = new_cIDs[0];
171 jetIDs[new_cIDs[0]] = newjet_k;
172 if (new_cIDs.size() == 2) {
173 coordIDs[newjet_k].mirror = new_cIDs[1];
174 jetIDs[new_cIDs[1]] = newjet_k;
175 } else {coordIDs[newjet_k].mirror = Invalid;}
176
177 //// if we've reached one "active" jet we should exit...
178 //n_active--;
179 //if (n_active == 1) {break;}
180
181 } while(true);
182
183 // cross check to see what's going on...
184 //cerr << "Max tree depths after: ";
185 //cp.print_tree_depths(cerr);
186
187}
188
189
190//----------------------------------------------------------------------
191/// a variant of the closest pair clustering which uses a region of
192/// size 2pi+2R in phi.
193void ClusterSequence::_CP2DChan_cluster_2pi2R () {
194
195 if (_jet_algorithm != cambridge_algorithm) throw Error("CP2DChan clustering method called for a jet-finder that is not the cambridge algorithm");
196
197 // run the clustering with mirror copies kept such that only things
198 // within _Rparam of a border are mirrored
199 _CP2DChan_limited_cluster(_Rparam);
200
201 //
202 _do_Cambridge_inclusive_jets();
203}
204
205
206//----------------------------------------------------------------------
207/// a variant of the closest pair clustering which uses a region of
208/// size 2pi + 2*0.3 and then carries on with 2pi+2*R
209void ClusterSequence::_CP2DChan_cluster_2piMultD () {
210
211 // do a first run of clustering up to a small distance parameter,
212 if (_Rparam >= 0.39) {
213 _CP2DChan_limited_cluster(min(_Rparam/2,0.3));
214 }
215
216 // and then the final round of clustering
217 _CP2DChan_cluster_2pi2R ();
218}
219
220
221//----------------------------------------------------------------------
222/// a 4pi variant of the closest pair clustering
223void ClusterSequence::_CP2DChan_cluster () {
224
225 if (_jet_algorithm != cambridge_algorithm) throw Error("_CP2DChan_cluster called for a jet-finder that is not the cambridge algorithm");
226
227 unsigned int n = _jets.size();
228
229 vector<MirrorInfo> coordIDs(2*n); // link from original to mirror indices
230 vector<int> jetIDs(2*n); // link from mirror to original indices
231 vector<Coord2D> coords(2*n); // our coordinates (and copies)
232
233 // start things off...
234 double minrap = numeric_limits<double>::max();
235 double maxrap = -minrap;
236 int coord_index = 0;
237 for (unsigned i = 0; i < n; i++) {
238 // separate out points with infinite rapidity
239 if (_jets[i].E() == abs(_jets[i].pz()) && _jets[i].perp2() == 0.0) {
240 coordIDs[i] = MirrorInfo(BeamJet,BeamJet);
241 } else {
242 coordIDs[i].orig = coord_index;
243 coordIDs[i].mirror = coord_index+1;
244 coords[coord_index] = Coord2D(_jets[i].rap(), _jets[i].phi_02pi());
245 coords[coord_index+1] = Coord2D(_jets[i].rap(), _jets[i].phi_02pi()+twopi);
246 jetIDs[coord_index] = i;
247 jetIDs[coord_index+1] = i;
248 minrap = min(coords[coord_index].x,minrap);
249 maxrap = max(coords[coord_index].x,maxrap);
250 coord_index += 2;
251 }
252 }
253 // label remaining "mirror info" as saying that there are no jets
254 for (unsigned i = n; i < 2*n; i++) {coordIDs[i].orig = Invalid;}
255
256 // set them to their actual size...
257 coords.resize(coord_index);
258
259 // establish limits (with some leeway on rapidity)
260 Coord2D left_edge(minrap-1.0, 0.0);
261 Coord2D right_edge(maxrap+1.0, 2*twopi);
262
263 // now create the closest pair search object
264 ClosestPair2D cp(coords, left_edge, right_edge);
265
266 // and start iterating...
267 vector<Coord2D> new_points(2);
268 vector<unsigned int> cIDs_to_remove(4);
269 vector<unsigned int> new_cIDs(2);
270 do {
271 // find out which pair we recombine
272 unsigned int cID1, cID2;
273 double distance2;
274 cp.closest_pair(cID1,cID2,distance2);
275 distance2 *= _invR2;
276
277 // if the closest distance > 1, we exit and go to "inclusive" stage
278 if (distance2 > 1.0) {break;}
279
280 // do the recombination...
281 int jet_i = jetIDs[cID1];
282 int jet_j = jetIDs[cID2];
283 int newjet_k;
284 _do_ij_recombination_step(jet_i, jet_j, distance2, newjet_k);
285
286 // now prepare operations on CP structure
287 cIDs_to_remove[0] = coordIDs[jet_i].orig;
288 cIDs_to_remove[1] = coordIDs[jet_i].mirror;
289 cIDs_to_remove[2] = coordIDs[jet_j].orig;
290 cIDs_to_remove[3] = coordIDs[jet_j].mirror;
291 new_points[0] = Coord2D(_jets[newjet_k].rap(),_jets[newjet_k].phi_02pi());
292 new_points[1] = Coord2D(_jets[newjet_k].rap(),_jets[newjet_k].phi_02pi()+twopi);
293 // carry out the CP operation
294 //cp.replace_many(cIDs_to_remove, new_points, new_cIDs);
295 // remarkable the following is faster...
296 new_cIDs[0] = cp.replace(cIDs_to_remove[0], cIDs_to_remove[2], new_points[0]);
297 new_cIDs[1] = cp.replace(cIDs_to_remove[1], cIDs_to_remove[3], new_points[1]);
298 // signal that the following jets no longer exist
299 coordIDs[jet_i].orig = Invalid;
300 coordIDs[jet_j].orig = Invalid;
301 // and do bookkeeping for new jet
302 coordIDs[newjet_k] = MirrorInfo(new_cIDs[0], new_cIDs[1]);
303 jetIDs[new_cIDs[0]] = newjet_k;
304 jetIDs[new_cIDs[1]] = newjet_k;
305
306 // if we've reached one jet we should exit...
307 n--;
308 if (n == 1) {break;}
309
310 } while(true);
311
312
313 // now do "beam" recombinations
314 //for (unsigned int jet_i = 0; jet_i < coordIDs.size(); jet_i++) {
315 // // if we have a predeclared beam jet or a valid set of mirror
316 // // coordinates, recombine then recombine this jet with the beam
317 // if (coordIDs[jet_i].orig == BeamJet || coordIDs[jet_i].orig > 0) {
318 // // diB = 1 _always_ (for the cambridge alg.)
319 // _do_iB_recombination_step(jet_i, 1.0);
320 // }
321 //}
322
323 _do_Cambridge_inclusive_jets();
324
325 //n = _history.size();
326 //for (unsigned int hist_i = 0; hist_i < n; hist_i++) {
327 // if (_history[hist_i].child == Invalid) {
328 // _do_iB_recombination_step(_history[hist_i].jetp_index, 1.0);
329 // }
330 //}
331
332}
333
334
335//----------------------------------------------------------------------
336void ClusterSequence::_do_Cambridge_inclusive_jets () {
337 unsigned int n = _history.size();
338 for (unsigned int hist_i = 0; hist_i < n; hist_i++) {
339 if (_history[hist_i].child == Invalid) {
340 _do_iB_recombination_step(_history[hist_i].jetp_index, 1.0);
341 }
342 }
343}
344
345FASTJET_END_NAMESPACE
346
Note: See TracBrowser for help on using the repository browser.