ClusterSequence_CP2DChan.cc

00001 //STARTHEADER
00002 // $Id: ClusterSequence_CP2DChan.cc 1821 2010-11-21 21:15:35Z salam $
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 {
00045   class MirrorInfo{
00046   public:
00047     int orig, mirror;
00048     MirrorInfo(int a, int b) : orig(a), mirror(b) {};
00049     MirrorInfo() {};
00050   };
00051 
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 //----------------------------------------------------------------------
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   // start things off...
00078   double minrap = numeric_limits<double>::max();
00079   double maxrap = -minrap;
00080   int coord_index = -1;
00081   int n_active = 0;
00082   for (unsigned jet_i = 0; jet_i < _jets.size(); jet_i++) {
00083 
00084     // skip jets that already have children or that have infinite
00085     // rapidity
00086     if (_history[_jets[jet_i].cluster_hist_index()].child != Invalid ||
00087         (_jets[jet_i].E() == abs(_jets[jet_i].pz()) && 
00088          _jets[jet_i].perp2() == 0.0)
00089         ) {continue;}
00090 
00091     n_active++;
00092 
00093     coordIDs[jet_i].orig = ++coord_index;
00094     coords[coord_index]  = Coord2D(_jets[jet_i].rap(), _jets[jet_i].phi_02pi());
00095     jetIDs[coord_index]  = jet_i;
00096     minrap = min(coords[coord_index].x,minrap);
00097     maxrap = max(coords[coord_index].x,maxrap);
00098 
00099     Coord2D mirror_point(coords[coord_index]);
00100     if (make_mirror(mirror_point, Dlim)) {
00101       coordIDs[jet_i].mirror = ++coord_index;
00102       coords[coord_index] = mirror_point;
00103       jetIDs[coord_index] = jet_i;
00104     } else {
00105       coordIDs[jet_i].mirror = Invalid;
00106     }
00107   }
00108 
00109   // set them to their actual size...
00110   coords.resize(coord_index+1);
00111 
00112   // establish limits (with some leeway on rapidity)
00113   Coord2D left_edge(minrap-1.0, -pi);
00114   Coord2D right_edge(maxrap+1.0, 3*pi);
00115 
00116   //cerr << "minrap, maxrap = " << minrap << " " << maxrap << endl;
00117 
00118   // now create the closest pair search object
00119   ClosestPair2D cp(coords, left_edge, right_edge);
00120 
00121   // cross check to see what's going on...
00122   //cerr << "Tree depths before: ";
00123   //cp.print_tree_depths(cerr);
00124 
00125   // and start iterating...
00126   vector<Coord2D> new_points(2);
00127   vector<unsigned int> cIDs_to_remove(4);
00128   vector<unsigned int> new_cIDs(2);
00129 
00130   do {
00131     // find out which pair we recombine
00132     unsigned int cID1, cID2;
00133     double distance2;
00134     cp.closest_pair(cID1,cID2,distance2);
00135 
00136     // if the closest distance > Dlim, we exit and go to "inclusive" stage
00137     if (distance2 > Dlim*Dlim) {break;}
00138 
00139     // normalise distance as we like it
00140     distance2 *= _invR2;
00141 
00142     // do the recombination...
00143     int jet_i = jetIDs[cID1];
00144     int jet_j = jetIDs[cID2];
00145     assert (jet_i != jet_j); // to catch issue of recombining with mirror point
00146     int newjet_k;
00147     _do_ij_recombination_step(jet_i, jet_j, distance2, newjet_k);
00148 
00149     // don't bother with any further action if only one active particle
00150     // is left (also avoid closest-pair error [cannot remove last particle]).
00151     if (--n_active == 1) {break;}
00152 
00153     // now prepare operations on CP structure
00154     cIDs_to_remove.resize(0);
00155     cIDs_to_remove.push_back(coordIDs[jet_i].orig);
00156     cIDs_to_remove.push_back(coordIDs[jet_j].orig);
00157     if (coordIDs[jet_i].mirror != Invalid) 
00158       cIDs_to_remove.push_back(coordIDs[jet_i].mirror);
00159     if (coordIDs[jet_j].mirror != Invalid) 
00160       cIDs_to_remove.push_back(coordIDs[jet_j].mirror);
00161 
00162     Coord2D new_point(_jets[newjet_k].rap(),_jets[newjet_k].phi_02pi());
00163     new_points.resize(0);
00164     new_points.push_back(new_point);
00165     if (make_mirror(new_point, Dlim)) new_points.push_back(new_point);
00166     
00167     // carry out actions on search tree
00168     cp.replace_many(cIDs_to_remove, new_points, new_cIDs);
00169 
00170     // now fill in info for new points...
00171     coordIDs[newjet_k].orig = new_cIDs[0];
00172     jetIDs[new_cIDs[0]]       = newjet_k;
00173     if (new_cIDs.size() == 2) {
00174       coordIDs[newjet_k].mirror = new_cIDs[1];
00175       jetIDs[new_cIDs[1]]         = newjet_k;
00176     } else {coordIDs[newjet_k].mirror = Invalid;}
00177     
00179     //n_active--;
00180     //if (n_active == 1) {break;}
00181 
00182   } while(true);
00183   
00184   // cross check to see what's going on...
00185   //cerr << "Max tree depths after: ";
00186   //cp.print_tree_depths(cerr);
00187 
00188 }
00189 
00190 
00191 //----------------------------------------------------------------------
00194 void ClusterSequence::_CP2DChan_cluster_2pi2R () {
00195 
00196   if (_jet_algorithm != cambridge_algorithm) throw Error("CP2DChan clustering method called for a jet-finder that is not the cambridge algorithm");
00197 
00198   // run the clustering with mirror copies kept such that only things
00199   // within _Rparam of a border are mirrored
00200   _CP2DChan_limited_cluster(_Rparam);
00201 
00202   //
00203   _do_Cambridge_inclusive_jets();
00204 }
00205 
00206 
00207 //----------------------------------------------------------------------
00210 void ClusterSequence::_CP2DChan_cluster_2piMultD () {
00211 
00212   // do a first run of clustering up to a small distance parameter,
00213   if (_Rparam >= 0.39) {
00214     _CP2DChan_limited_cluster(min(_Rparam/2,0.3));
00215   }
00216 
00217   // and then the final round of clustering
00218   _CP2DChan_cluster_2pi2R ();
00219 }
00220 
00221 
00222 //----------------------------------------------------------------------
00224 void ClusterSequence::_CP2DChan_cluster () {
00225 
00226   if (_jet_algorithm != cambridge_algorithm) throw Error("_CP2DChan_cluster called for a jet-finder that is not the cambridge algorithm");
00227 
00228   unsigned int n = _jets.size();
00229 
00230   vector<MirrorInfo>   coordIDs(2*n);  // link from original to mirror indices
00231   vector<int>          jetIDs(2*n);     // link from mirror to original indices
00232   vector<Coord2D>      coords(2*n);   // our coordinates (and copies)
00233 
00234   // start things off...
00235   double minrap = numeric_limits<double>::max();
00236   double maxrap = -minrap;
00237   int coord_index = 0;
00238   for (unsigned i = 0; i < n; i++) {
00239     // separate out points with infinite rapidity
00240     if (_jets[i].E() == abs(_jets[i].pz()) && _jets[i].perp2() == 0.0) {
00241       coordIDs[i] = MirrorInfo(BeamJet,BeamJet);
00242     } else {
00243       coordIDs[i].orig   = coord_index;
00244       coordIDs[i].mirror = coord_index+1;
00245       coords[coord_index]   = Coord2D(_jets[i].rap(), _jets[i].phi_02pi());
00246       coords[coord_index+1] = Coord2D(_jets[i].rap(), _jets[i].phi_02pi()+twopi);
00247       jetIDs[coord_index]   = i;
00248       jetIDs[coord_index+1] = i;
00249       minrap = min(coords[coord_index].x,minrap);
00250       maxrap = max(coords[coord_index].x,maxrap);
00251       coord_index += 2;
00252     }
00253   }
00254   // label remaining "mirror info" as saying that there are no jets
00255   for (unsigned i = n; i < 2*n; i++) {coordIDs[i].orig = Invalid;}
00256 
00257   // set them to their actual size...
00258   coords.resize(coord_index);
00259 
00260   // establish limits (with some leeway on rapidity)
00261   Coord2D left_edge(minrap-1.0, 0.0);
00262   Coord2D right_edge(maxrap+1.0, 2*twopi);
00263 
00264   // now create the closest pair search object
00265   ClosestPair2D cp(coords, left_edge, right_edge);
00266 
00267   // and start iterating...
00268   vector<Coord2D> new_points(2);
00269   vector<unsigned int> cIDs_to_remove(4);
00270   vector<unsigned int> new_cIDs(2);
00271   do {
00272     // find out which pair we recombine
00273     unsigned int cID1, cID2;
00274     double distance2;
00275     cp.closest_pair(cID1,cID2,distance2);
00276     distance2 *= _invR2;
00277 
00278     // if the closest distance > 1, we exit and go to "inclusive" stage
00279     if (distance2 > 1.0) {break;}
00280 
00281     // do the recombination...
00282     int jet_i = jetIDs[cID1];
00283     int jet_j = jetIDs[cID2];
00284     assert (jet_i != jet_j); // to catch issue of recombining with mirror point
00285     int newjet_k;
00286     _do_ij_recombination_step(jet_i, jet_j, distance2, newjet_k);
00287 
00288     // now prepare operations on CP structure
00289     cIDs_to_remove[0] = coordIDs[jet_i].orig;
00290     cIDs_to_remove[1] = coordIDs[jet_i].mirror;
00291     cIDs_to_remove[2] = coordIDs[jet_j].orig;
00292     cIDs_to_remove[3] = coordIDs[jet_j].mirror;
00293     new_points[0] = Coord2D(_jets[newjet_k].rap(),_jets[newjet_k].phi_02pi());
00294     new_points[1] = Coord2D(_jets[newjet_k].rap(),_jets[newjet_k].phi_02pi()+twopi);
00295     // carry out the CP operation
00296     //cp.replace_many(cIDs_to_remove, new_points, new_cIDs);
00297     // remarkable the following is faster...
00298     new_cIDs[0] = cp.replace(cIDs_to_remove[0], cIDs_to_remove[2], new_points[0]);
00299     new_cIDs[1] = cp.replace(cIDs_to_remove[1], cIDs_to_remove[3], new_points[1]);
00300     // signal that the following jets no longer exist
00301     coordIDs[jet_i].orig = Invalid;
00302     coordIDs[jet_j].orig = Invalid;
00303     // and do bookkeeping for new jet
00304     coordIDs[newjet_k] = MirrorInfo(new_cIDs[0], new_cIDs[1]);
00305     jetIDs[new_cIDs[0]] = newjet_k;
00306     jetIDs[new_cIDs[1]] = newjet_k;
00307 
00308     // if we've reached one jet we should exit...
00309     n--;
00310     if (n == 1) {break;}
00311 
00312   } while(true);
00313   
00314 
00315   // now do "beam" recombinations 
00316   //for (unsigned int jet_i = 0; jet_i < coordIDs.size(); jet_i++) {
00317   //  // if we have a predeclared beam jet or a valid set of mirror
00318   //  // coordinates, recombine then recombine this jet with the beam
00319   //  if (coordIDs[jet_i].orig == BeamJet || coordIDs[jet_i].orig > 0) {
00320   //    // diB = 1 _always_ (for the cambridge alg.)
00321   //    _do_iB_recombination_step(jet_i, 1.0);
00322   //  }
00323   //}
00324 
00325   _do_Cambridge_inclusive_jets();
00326 
00327   //n = _history.size();
00328   //for (unsigned int hist_i = 0; hist_i < n; hist_i++) {
00329   //  if (_history[hist_i].child == Invalid) {
00330   //    _do_iB_recombination_step(_history[hist_i].jetp_index, 1.0);
00331   //  }
00332   //}
00333 
00334 }
00335 
00336 
00337 //----------------------------------------------------------------------
00338 void ClusterSequence::_do_Cambridge_inclusive_jets () {
00339   unsigned int n = _history.size();
00340   for (unsigned int hist_i = 0; hist_i < n; hist_i++) {
00341     if (_history[hist_i].child == Invalid) {
00342       _do_iB_recombination_step(_history[hist_i].jetp_index, 1.0);
00343     }
00344   }
00345 }
00346 
00347 FASTJET_END_NAMESPACE
00348