SISCone  2.0.5
siscone/vicinity.cpp
00001 
00002 // File: vicinity.cpp                                                        //
00003 // Description: source file for particle vicinity (Cvicinity class)          //
00004 // This file is part of the SISCone project.                                 //
00005 // For more details, see http://projects.hepforge.org/siscone                //
00006 //                                                                           //
00007 // Copyright (c) 2006 Gavin Salam and Gregory Soyez                          //
00008 //                                                                           //
00009 // This program 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 // This program is distributed in the hope that it will be useful,           //
00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of            //
00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             //
00017 // GNU General Public License for more details.                              //
00018 //                                                                           //
00019 // You should have received a copy of the GNU General Public License         //
00020 // along with this program; if not, write to the Free Software               //
00021 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA //
00022 //                                                                           //
00023 // $Revision:: 123                                                          $//
00024 // $Date:: 2007-03-01 02:52:16 +0100 (Thu, 01 Mar 2007)                     $//
00026 
00027 #include "vicinity.h"
00028 #include <math.h>
00029 #include <algorithm>
00030 #include <iostream>
00031 
00032 namespace siscone{
00033 
00034 using namespace std;
00035 
00036 /*************************************************************
00037  * Cvicinity_elm implementation                              *
00038  * element in the vicinity of a parent.                      *
00039  * class used to manage one points in the vicinity           *
00040  * of a parent point.                                        *
00041  *************************************************************/
00042 
00043 // ordering pointers to Cvicinity_elm
00044 //------------------------------------
00045 bool ve_less(Cvicinity_elm *ve1, Cvicinity_elm *ve2){
00046   return ve1->angle < ve2->angle;
00047 }
00048 
00049 
00050 /*************************************************************
00051  * Cvicinity implementation                                  *
00052  * list of element in the vicinity of a parent.              *
00053  * class used to manage the points which are in the vicinity *
00054  * of a parent point. The construction of the list can be    *
00055  * made from a list of points or from a quadtree.            *
00056  *************************************************************/
00057 
00058 // default constructor
00059 //---------------------
00060 Cvicinity::Cvicinity(){
00061   n_part = 0;
00062 
00063   ve_list = NULL;
00064 #ifdef USE_QUADTREE_FOR_STABILITY_TEST
00065   quadtree = NULL;
00066 #endif
00067 
00068   parent = NULL;
00069   VR2 = VR = 0.0;
00070 
00071 }
00072 
00073 // constructor with initialisation
00074 //---------------------------------
00075 Cvicinity::Cvicinity(vector<Cmomentum> &_particle_list){
00076   parent = NULL;
00077 #ifdef USE_QUADTREE_FOR_STABILITY_TEST
00078   quadtree = NULL;
00079 #endif
00080   VR2 = VR = 0.0;
00081 
00082   set_particle_list(_particle_list);
00083 }
00084 
00085 // default destructor
00086 //--------------------
00087 Cvicinity::~Cvicinity(){
00088   if (ve_list!=NULL)
00089     delete[] ve_list;
00090 
00091 #ifdef USE_QUADTREE_FOR_STABILITY_TEST
00092   if (quadtree!=NULL)
00093     delete quadtree;
00094 #endif
00095 }
00096 
00097 /*
00098  * set the particle_list
00099  *  - particle_list   list of particles (type Cmomentum)
00100  *  - n               number of particles in the list
00101  ************************************************************/ 
00102 void Cvicinity::set_particle_list(vector<Cmomentum> &_particle_list){
00103   int i,j;
00104 #ifdef USE_QUADTREE_FOR_STABILITY_TEST
00105   double eta_max=0.0;
00106 #endif
00107   
00108   // if the particle list is not empty, destroy it !
00109   if (ve_list!=NULL){
00110     delete[] ve_list;
00111   }
00112   vicinity.clear();
00113 #ifdef USE_QUADTREE_FOR_STABILITY_TEST
00114   if (quadtree!=NULL)
00115     delete quadtree;
00116 #endif
00117 
00118   // allocate memory array for particles
00119   // Note: - we compute max for |eta|
00120   //       - we allocate indices to particles
00121   n_part = 0;
00122   plist.clear();
00123   pincluded.clear();
00124   for (i=0;i<(int) _particle_list.size();i++){
00125     // if a particle is colinear with the beam (infinite rapidity)
00126     // we do not take it into account
00127     if (fabs(_particle_list[i].pz)!=_particle_list[i].E){
00128       plist.push_back(_particle_list[i]);
00129       pincluded.push_back(Cvicinity_inclusion()); // zero inclusion status
00130 
00131       // the parent_index is handled in the split_merge because 
00132       // of our multiple-pass procedure.
00133       // Hence, it is not required here any longer.
00134       // plist[n_part].parent_index = i;
00135       plist[n_part].index = n_part;
00136 
00137       // make sure the reference is randomly created
00138       plist[n_part].ref.randomize();
00139 
00140 #ifdef USE_QUADTREE_FOR_STABILITY_TEST
00141       if (fabs(plist[n_part].eta)>eta_max) eta_max=fabs(plist[n_part].eta);
00142 #endif
00143 
00144       n_part++;
00145     }
00146   }
00147 
00148   // allocate quadtree and vicinity_elm list
00149   // note: we set phi in [-pi:pi] as it is the natural range for atan2!
00150   ve_list = new Cvicinity_elm[2*n_part];
00151 #ifdef USE_QUADTREE_FOR_STABILITY_TEST
00152   eta_max+=0.1;
00153   quadtree = new Cquadtree(0.0, 0.0, eta_max, M_PI);
00154 #endif
00155 
00156   // append particle to the vicinity_elm list
00157   j = 0;
00158   for (i=0;i<n_part;i++){
00159 #ifdef USE_QUADTREE_FOR_STABILITY_TEST
00160     quadtree->add(&plist[i]);
00161 #endif
00162     ve_list[j].v = ve_list[j+1].v = &plist[i];
00163     ve_list[j].is_inside = ve_list[j+1].is_inside = &(pincluded[i]);
00164     j+=2;
00165   }
00166 
00167 }
00168 
00169 
00170 /*
00171  * build the vicinity list from a list of points.
00172  *  - _parent   reference particle
00173  *  - _VR       vicinity radius
00174  ************************************************************/
00175 void Cvicinity::build(Cmomentum *_parent, double _VR){
00176   int i;
00177 
00178   // set parent and radius
00179   parent = _parent;
00180   VR  = _VR;
00181   VR2 = VR*VR;
00182   R2  = 0.25*VR2;
00183   R   = 0.5*VR;
00184   inv_R_EPS_COCIRC  = 1.0 / R / EPSILON_COCIRCULAR;
00185   inv_R_2EPS_COCIRC = 0.5 / R / EPSILON_COCIRCULAR;
00186 
00187   // clear vicinity
00188   vicinity.clear();
00189 
00190   // init parent variables
00191   pcx = parent->eta;
00192   pcy = parent->phi;
00193 
00194   // really browse the particle list
00195   for (i=0;i<n_part;i++){
00196     append_to_vicinity(&plist[i]);
00197   }
00198 
00199   // sort the vicinity
00200   sort(vicinity.begin(), vicinity.end(), ve_less);
00201 
00202   vicinity_size = vicinity.size();
00203 }
00204 
00205 
00207 inline double sort_angle(double s, double c){
00208   if (s==0) return (c>0) ? 0.0 : 2.0;
00209   double t=c/s;
00210   return (s>0) ? 1-t/(1+fabs(t)) : 3-t/(1+fabs(t));
00211 }
00212 
00213 
00214 /*
00215  * append a particle to the 'vicinity' list after
00216  * having computed the angular-ordering quantities
00217  *  - v   vector to test
00218  **********************************************************/
00219 void Cvicinity::append_to_vicinity(Cmomentum *v){
00220   double dx, dy, d2;
00221 
00222   // skip the particle itself)
00223   if (v==parent)
00224     return;
00225 
00226   int i=2*(v->index);
00227 
00228   // compute the distance of the i-th particle with the parent
00229   dx = v->eta - pcx;
00230   dy = v->phi - pcy;
00231     
00232   // pay attention to the periodicity in phi !
00233   if (dy>M_PI) 
00234     dy -= twopi;
00235   else if (dy<-M_PI) 
00236     dy += twopi;
00237 
00238   d2 = dx*dx+dy*dy;
00239     
00240   // really check if the distance is less than VR
00241   if (d2<VR2){
00242     double s,c,tmp;
00243     
00244     // compute the angles used for future ordering ...
00245     //  - build temporary variables used for the computation
00246     //d   = sqrt(d2);
00247     tmp = sqrt(VR2/d2-1);
00248 
00249     // first angle (+)
00250     c = 0.5*(dx-dy*tmp);  // cosine of (parent,child) pair w.r.t. horizontal
00251     s = 0.5*(dy+dx*tmp);  // sine   of (parent,child) pair w.r.t. horizontal
00252     ve_list[i].angle = sort_angle(s,c);
00253     ve_list[i].eta = pcx+c;
00254     ve_list[i].phi = phi_in_range(pcy+s);
00255     ve_list[i].side = true;
00256     ve_list[i].cocircular.clear();
00257     vicinity.push_back(&(ve_list[i]));
00258 
00259     // second angle (-)    
00260     c = 0.5*(dx+dy*tmp);  // cosine of (parent,child) pair w.r.t. horizontal
00261     s = 0.5*(dy-dx*tmp);  // sine   of (parent,child) pair w.r.t. horizontal
00262     ve_list[i+1].angle = sort_angle(s,c);
00263     ve_list[i+1].eta = pcx+c;
00264     ve_list[i+1].phi = phi_in_range(pcy+s);
00265     ve_list[i+1].side = false;
00266     ve_list[i+1].cocircular.clear();
00267     vicinity.push_back(&(ve_list[i+1]));
00268 
00269     // now work out the cocircularity range for the two points (range
00270     // of angle within which the points stay within a distance
00271     // EPSILON_COCIRCULAR of circule
00272     // P = parent; C = child; O = Origin (center of circle)
00273     Ctwovect OP(pcx - ve_list[i+1].eta, phi_in_range(pcy-ve_list[i+1].phi));
00274     Ctwovect OC(v->eta - ve_list[i+1].eta, 
00275                 phi_in_range(v->phi-ve_list[i+1].phi));
00276 
00277     // two sources of error are (GPS CCN29-19) epsilon/(R sin theta)
00278     // and sqrt(2*epsilon/(R (1-cos theta))) and the way things work
00279     // out, it is the _smaller_ of the two that is relevant [NB have
00280     // changed definition of theta here relative to that used in
00281     // CCN29] [NB2: write things so as to avoid zero denominators and
00282     // to minimize the multiplications, divisions and above all sqrts
00283     // -- that means that c & s are defined including a factor of VR2]
00284     c = dot_product(OP,OC);
00285     s = fabs(cross_product(OP,OC));
00286     double inv_err1 = s * inv_R_EPS_COCIRC;
00287     double inv_err2_sq = (R2-c) * inv_R_2EPS_COCIRC;
00288     ve_list[i].cocircular_range = pow2(inv_err1) > inv_err2_sq ? 
00289                                                      1.0/inv_err1 : 
00290                                                      sqrt(1.0/inv_err2_sq);
00291     ve_list[i+1].cocircular_range = ve_list[i].cocircular_range;
00292   }
00293 }
00294 
00295 }
The SISCone project has been developed by Gavin Salam and Gregory Soyez
Documentation generated on Mon Jun 4 2012 18:23:38 for SISCone by  Doxygen 1.7.6.1