FastJet 3.0beta1
ClusterSequence_CP2DChan.cc
00001 //STARTHEADER
00002 // $Id: ClusterSequence_CP2DChan.cc 1938 2011-02-08 15:06:00Z soyez $
00003 //
00004 // Copyright (c) 2005-2006, Matteo Cacciari and Gavin Salam
00005 //
00006 //----------------------------------------------------------------------
00007 // This file is part of FastJet.
00008 //
00009 //  FastJet is free software; you can redistribute it and/or modify
00010 //  it under the terms of the GNU General Public License as published by
00011 //  the Free Software Foundation; either version 2 of the License, or
00012 //  (at your option) any later version.
00013 //
00014 //  The algorithms that underlie FastJet have required considerable
00015 //  development and are described in hep-ph/0512210. If you use
00016 //  FastJet as part of work towards a scientific publication, please
00017 //  include a citation to the FastJet paper.
00018 //
00019 //  FastJet is distributed in the hope that it will be useful,
00020 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
00021 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00022 //  GNU General Public License for more details.
00023 //
00024 //  You should have received a copy of the GNU General Public License
00025 //  along with FastJet; if not, write to the Free Software
00026 //  Foundation, Inc.:
00027 //      59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00028 //----------------------------------------------------------------------
00029 //ENDHEADER
00030 
00031 #include "fastjet/ClusterSequence.hh"
00032 #include "fastjet/internal/ClosestPair2D.hh"
00033 #include<limits>
00034 #include<vector>
00035 #include<cmath>
00036 #include<iostream>
00037 
00038 FASTJET_BEGIN_NAMESPACE      // defined in fastjet/internal/base.hh
00039 
00040 using namespace std;
00041 
00042 // place for things we don't want outside world to run into
00043 namespace Private {
00044   /// class for helping us deal with mirror-image particles.
00045   class MirrorInfo{
00046   public:
00047     int orig, mirror;
00048     MirrorInfo(int a, int b) : orig(a), mirror(b) {};
00049     MirrorInfo() {};
00050   };
00051 
00052   /// if there is a need for a mirror when looking for closest pairs
00053   /// up to distance D, then return true and turn the supplied point
00054   /// into its mirror copy
00055   bool make_mirror(Coord2D & point, double Dlim) {
00056     if (point.y < Dlim)       {point.y += twopi; return true;}
00057     if (twopi-point.y < Dlim) {point.y -= twopi; return true;}
00058     return false;
00059   }
00060   
00061 }
00062 
00063 using namespace Private;
00064 
00065 
00066 //----------------------------------------------------------------------
00067 /// clusters only up to a distance Dlim -- does not deal with "inclusive" jets
00068 /// -- these are left to some other part of the program
00069 void ClusterSequence::_CP2DChan_limited_cluster (double Dlim) {
00070   
00071   unsigned int n = _initial_n;
00072 
00073   vector<MirrorInfo>   coordIDs(2*n); // coord IDs of a given jetID
00074   vector<int>          jetIDs(2*n);   // jet ID for a given coord ID
00075   vector<Coord2D>      coords(2*n);   // our coordinates (and copies)
00076 
00077   // particles within a distance Dlim of the phi edges (phi<Dlim ||
00078   // phi>2pi-Dli;) will be mirrored. For Dlim>pi, this could lead to
00079   // particles copies outside the fixed range in phi which is
00080   // [-pi:3pi] (see make_mirror above). Since in that case all
00081   // particles get copied anywaym we can just copy particles up to a
00082   // distance "pi" from the edges
00083   double Dlim4mirror = min(Dlim,pi);
00084 
00085   // start things off...
00086   double minrap = numeric_limits<double>::max();
00087   double maxrap = -minrap;
00088   int coord_index = -1;
00089   int n_active = 0;
00090   for (unsigned jet_i = 0; jet_i < _jets.size(); jet_i++) {
00091 
00092     // skip jets that already have children or that have infinite
00093     // rapidity
00094     if (_history[_jets[jet_i].cluster_hist_index()].child != Invalid ||
00095         (_jets[jet_i].E() == abs(_jets[jet_i].pz()) && 
00096          _jets[jet_i].perp2() == 0.0)
00097         ) {continue;}
00098 
00099     n_active++;
00100 
00101     coordIDs[jet_i].orig = ++coord_index;
00102     coords[coord_index]  = Coord2D(_jets[jet_i].rap(), _jets[jet_i].phi_02pi());
00103     jetIDs[coord_index]  = jet_i;
00104     minrap = min(coords[coord_index].x,minrap);
00105     maxrap = max(coords[coord_index].x,maxrap);
00106 
00107     Coord2D mirror_point(coords[coord_index]);
00108     if (make_mirror(mirror_point, Dlim4mirror)) {
00109       coordIDs[jet_i].mirror = ++coord_index;
00110       coords[coord_index] = mirror_point;
00111       jetIDs[coord_index] = jet_i;
00112     } else {
00113       coordIDs[jet_i].mirror = Invalid;
00114     }
00115   }
00116 
00117   // set them to their actual size...
00118   coords.resize(coord_index+1);
00119 
00120   // establish limits (with some leeway on rapidity)
00121   Coord2D left_edge(minrap-1.0, -3.15); // a security margin below  -pi
00122   Coord2D right_edge(maxrap+1.0, 9.45); // a security margin above 3*pi
00123 
00124   //cerr << "minrap, maxrap = " << minrap << " " << maxrap << endl;
00125 
00126   // now create the closest pair search object
00127   ClosestPair2D cp(coords, left_edge, right_edge);
00128 
00129   // cross check to see what's going on...
00130   //cerr << "Tree depths before: ";
00131   //cp.print_tree_depths(cerr);
00132 
00133   // and start iterating...
00134   vector<Coord2D> new_points(2);
00135   vector<unsigned int> cIDs_to_remove(4);
00136   vector<unsigned int> new_cIDs(2);
00137 
00138   do {
00139     // find out which pair we recombine
00140     unsigned int cID1, cID2;
00141     double distance2;
00142     cp.closest_pair(cID1,cID2,distance2);
00143 
00144     // if the closest distance > Dlim, we exit and go to "inclusive" stage
00145     if (distance2 > Dlim*Dlim) {break;}
00146 
00147     // normalise distance as we like it
00148     distance2 *= _invR2;
00149 
00150     // do the recombination...
00151     int jet_i = jetIDs[cID1];
00152     int jet_j = jetIDs[cID2];
00153     assert (jet_i != jet_j); // to catch issue of recombining with mirror point
00154     int newjet_k;
00155     _do_ij_recombination_step(jet_i, jet_j, distance2, newjet_k);
00156 
00157     // don't bother with any further action if only one active particle
00158     // is left (also avoid closest-pair error [cannot remove last particle]).
00159     if (--n_active == 1) {break;}
00160 
00161     // now prepare operations on CP structure
00162     cIDs_to_remove.resize(0);
00163     cIDs_to_remove.push_back(coordIDs[jet_i].orig);
00164     cIDs_to_remove.push_back(coordIDs[jet_j].orig);
00165     if (coordIDs[jet_i].mirror != Invalid) 
00166       cIDs_to_remove.push_back(coordIDs[jet_i].mirror);
00167     if (coordIDs[jet_j].mirror != Invalid) 
00168       cIDs_to_remove.push_back(coordIDs[jet_j].mirror);
00169 
00170     Coord2D new_point(_jets[newjet_k].rap(),_jets[newjet_k].phi_02pi());
00171     new_points.resize(0);
00172     new_points.push_back(new_point);
00173     if (make_mirror(new_point, Dlim4mirror)) new_points.push_back(new_point);  //< same warning as before concerning the mirroring
00174     
00175     // carry out actions on search tree
00176     cp.replace_many(cIDs_to_remove, new_points, new_cIDs);
00177 
00178     // now fill in info for new points...
00179     coordIDs[newjet_k].orig = new_cIDs[0];
00180     jetIDs[new_cIDs[0]]       = newjet_k;
00181     if (new_cIDs.size() == 2) {
00182       coordIDs[newjet_k].mirror = new_cIDs[1];
00183       jetIDs[new_cIDs[1]]         = newjet_k;
00184     } else {coordIDs[newjet_k].mirror = Invalid;}
00185     
00186     //// if we've reached one "active" jet we should exit...
00187     //n_active--;
00188     //if (n_active == 1) {break;}
00189 
00190   } while(true);
00191   
00192   // cross check to see what's going on...
00193   //cerr << "Max tree depths after: ";
00194   //cp.print_tree_depths(cerr);
00195 
00196 }
00197 
00198 
00199 //----------------------------------------------------------------------
00200 /// a variant of the closest pair clustering which uses a region of
00201 /// size 2pi+2R in phi.
00202 void ClusterSequence::_CP2DChan_cluster_2pi2R () {
00203 
00204   if (_jet_algorithm != cambridge_algorithm) throw Error("CP2DChan clustering method called for a jet-finder that is not the cambridge algorithm");
00205 
00206   // run the clustering with mirror copies kept such that only things
00207   // within _Rparam of a border are mirrored
00208   _CP2DChan_limited_cluster(_Rparam);
00209 
00210   //
00211   _do_Cambridge_inclusive_jets();
00212 }
00213 
00214 
00215 //----------------------------------------------------------------------
00216 /// a variant of the closest pair clustering which uses a region of
00217 /// size 2pi + 2*0.3 and then carries on with 2pi+2*R
00218 void ClusterSequence::_CP2DChan_cluster_2piMultD () {
00219 
00220   // do a first run of clustering up to a small distance parameter,
00221   if (_Rparam >= 0.39) {
00222     _CP2DChan_limited_cluster(min(_Rparam/2,0.3));
00223   }
00224 
00225   // and then the final round of clustering
00226   _CP2DChan_cluster_2pi2R ();
00227 }
00228 
00229 
00230 //----------------------------------------------------------------------
00231 /// a 4pi variant of the closest pair clustering
00232 void ClusterSequence::_CP2DChan_cluster () {
00233 
00234   if (_jet_algorithm != cambridge_algorithm) throw Error("_CP2DChan_cluster called for a jet-finder that is not the cambridge algorithm");
00235 
00236   unsigned int n = _jets.size();
00237 
00238   vector<MirrorInfo>   coordIDs(2*n);  // link from original to mirror indices
00239   vector<int>          jetIDs(2*n);     // link from mirror to original indices
00240   vector<Coord2D>      coords(2*n);   // our coordinates (and copies)
00241 
00242   // start things off...
00243   double minrap = numeric_limits<double>::max();
00244   double maxrap = -minrap;
00245   int coord_index = 0;
00246   for (unsigned i = 0; i < n; i++) {
00247     // separate out points with infinite rapidity
00248     if (_jets[i].E() == abs(_jets[i].pz()) && _jets[i].perp2() == 0.0) {
00249       coordIDs[i] = MirrorInfo(BeamJet,BeamJet);
00250     } else {
00251       coordIDs[i].orig   = coord_index;
00252       coordIDs[i].mirror = coord_index+1;
00253       coords[coord_index]   = Coord2D(_jets[i].rap(), _jets[i].phi_02pi());
00254       coords[coord_index+1] = Coord2D(_jets[i].rap(), _jets[i].phi_02pi()+twopi);
00255       jetIDs[coord_index]   = i;
00256       jetIDs[coord_index+1] = i;
00257       minrap = min(coords[coord_index].x,minrap);
00258       maxrap = max(coords[coord_index].x,maxrap);
00259       coord_index += 2;
00260     }
00261   }
00262   // label remaining "mirror info" as saying that there are no jets
00263   for (unsigned i = n; i < 2*n; i++) {coordIDs[i].orig = Invalid;}
00264 
00265   // set them to their actual size...
00266   coords.resize(coord_index);
00267 
00268   // establish limits (with some leeway on rapidity)
00269   Coord2D left_edge(minrap-1.0, 0.0);
00270   Coord2D right_edge(maxrap+1.0, 2*twopi);
00271 
00272   // now create the closest pair search object
00273   ClosestPair2D cp(coords, left_edge, right_edge);
00274 
00275   // and start iterating...
00276   vector<Coord2D> new_points(2);
00277   vector<unsigned int> cIDs_to_remove(4);
00278   vector<unsigned int> new_cIDs(2);
00279   do {
00280     // find out which pair we recombine
00281     unsigned int cID1, cID2;
00282     double distance2;
00283     cp.closest_pair(cID1,cID2,distance2);
00284     distance2 *= _invR2;
00285 
00286     // if the closest distance > 1, we exit and go to "inclusive" stage
00287     if (distance2 > 1.0) {break;}
00288 
00289     // do the recombination...
00290     int jet_i = jetIDs[cID1];
00291     int jet_j = jetIDs[cID2];
00292     assert (jet_i != jet_j); // to catch issue of recombining with mirror point
00293     int newjet_k;
00294     _do_ij_recombination_step(jet_i, jet_j, distance2, newjet_k);
00295 
00296     // now prepare operations on CP structure
00297     cIDs_to_remove[0] = coordIDs[jet_i].orig;
00298     cIDs_to_remove[1] = coordIDs[jet_i].mirror;
00299     cIDs_to_remove[2] = coordIDs[jet_j].orig;
00300     cIDs_to_remove[3] = coordIDs[jet_j].mirror;
00301     new_points[0] = Coord2D(_jets[newjet_k].rap(),_jets[newjet_k].phi_02pi());
00302     new_points[1] = Coord2D(_jets[newjet_k].rap(),_jets[newjet_k].phi_02pi()+twopi);
00303     // carry out the CP operation
00304     //cp.replace_many(cIDs_to_remove, new_points, new_cIDs);
00305     // remarkable the following is faster...
00306     new_cIDs[0] = cp.replace(cIDs_to_remove[0], cIDs_to_remove[2], new_points[0]);
00307     new_cIDs[1] = cp.replace(cIDs_to_remove[1], cIDs_to_remove[3], new_points[1]);
00308     // signal that the following jets no longer exist
00309     coordIDs[jet_i].orig = Invalid;
00310     coordIDs[jet_j].orig = Invalid;
00311     // and do bookkeeping for new jet
00312     coordIDs[newjet_k] = MirrorInfo(new_cIDs[0], new_cIDs[1]);
00313     jetIDs[new_cIDs[0]] = newjet_k;
00314     jetIDs[new_cIDs[1]] = newjet_k;
00315 
00316     // if we've reached one jet we should exit...
00317     n--;
00318     if (n == 1) {break;}
00319 
00320   } while(true);
00321   
00322 
00323   // now do "beam" recombinations 
00324   //for (unsigned int jet_i = 0; jet_i < coordIDs.size(); jet_i++) {
00325   //  // if we have a predeclared beam jet or a valid set of mirror
00326   //  // coordinates, recombine then recombine this jet with the beam
00327   //  if (coordIDs[jet_i].orig == BeamJet || coordIDs[jet_i].orig > 0) {
00328   //    // diB = 1 _always_ (for the cambridge alg.)
00329   //    _do_iB_recombination_step(jet_i, 1.0);
00330   //  }
00331   //}
00332 
00333   _do_Cambridge_inclusive_jets();
00334 
00335   //n = _history.size();
00336   //for (unsigned int hist_i = 0; hist_i < n; hist_i++) {
00337   //  if (_history[hist_i].child == Invalid) {
00338   //    _do_iB_recombination_step(_history[hist_i].jetp_index, 1.0);
00339   //  }
00340   //}
00341 
00342 }
00343 
00344 
00345 //----------------------------------------------------------------------
00346 void ClusterSequence::_do_Cambridge_inclusive_jets () {
00347   unsigned int n = _history.size();
00348   for (unsigned int hist_i = 0; hist_i < n; hist_i++) {
00349     if (_history[hist_i].child == Invalid) {
00350       _do_iB_recombination_step(_history[hist_i].jetp_index, 1.0);
00351     }
00352   }
00353 }
00354 
00355 FASTJET_END_NAMESPACE
00356 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends