1#ifndef __FASTJET_NNFJN2TILED_HH__ 
    2#define __FASTJET_NNFJN2TILED_HH__ 
   34#include "fastjet/NNBase.hh" 
   35#include "fastjet/internal/TilingExtent.hh" 
   37FASTJET_BEGIN_NAMESPACE      
 
  118  NNFJN2Tiled(
const std::vector<PseudoJet> & jets, 
double requested_tile_size)
 
  119    : 
NNBase<I>(),     _requested_tile_size(requested_tile_size) {start(jets);}
 
  120  NNFJN2Tiled(
const std::vector<PseudoJet> & jets, 
double requested_tile_size, I * info)
 
  121    : 
NNBase<I>(info), _requested_tile_size(requested_tile_size) {start(jets);}
 
  123  void start(
const std::vector<PseudoJet> & jets);
 
  127  double dij_min(
int & iA, 
int & iB);
 
  130  void remove_jet(
int iA);
 
  134  void merge_jets(
int iA, 
int iB, 
const PseudoJet & jet, 
int jet_index);
 
  148  void _initialise_tiles(
const std::vector<PseudoJet> & particles);
 
  151  inline double _compute_diJ(
const TiledJet * 
const jet)
 const {
 
  152    double mom_fact = jet->momentum_factor();
 
  153    if (jet->NN != NULL) {
 
  154      double other_mom_fact = jet->NN->momentum_factor();
 
  155      if (other_mom_fact < mom_fact) {mom_fact = other_mom_fact;}
 
  157    return jet->NN_dist * mom_fact;
 
  162  inline int _tile_index (
int irap, 
int iphi)
 const {
 
  165    return (irap-_tiles_irap_min)*_n_tiles_phi
 
  166                  + (iphi+_n_tiles_phi) % _n_tiles_phi;
 
  169  int  _tile_index(
const double rap, 
const double phi) 
const;
 
  170  void _tiledjet_set_jetinfo ( TiledJet * 
const tiled_jet, 
const PseudoJet &jet, 
int index);
 
  171  void _bj_remove_from_tiles(TiledJet * 
const jet);
 
  172  void _initialise_tiles();
 
  173  void _print_tiles(TiledJet * briefjets ) 
const;
 
  174  void _add_neighbours_to_tile_union(
const int tile_index, 
int & n_near_tiles) 
const;
 
  175  void _add_untagged_neighbours_to_tile_union(
const int tile_index, 
int & n_near_tiles);
 
  179  TiledJet * briefjets;
 
  188  std::vector<TiledJet *> where_is;
 
  191  std::vector<int> tile_union;
 
  197  std::vector<Tile> _tiles;
 
  198  double _requested_tile_size;
 
  199  double _tiles_rap_min, _tiles_rap_max;
 
  200  double _tile_size_rap, _tile_size_phi;
 
  201  int    _n_tiles_phi,_tiles_irap_min,_tiles_irap_max;
 
  205  class TiledJet : 
public BJ {
 
  207    void init(
const PseudoJet & jet, 
int index_in) {
 
  209      other_init(index_in);
 
  211    void init(
const PseudoJet & jet, 
int index_in, I * info) {
 
  213      other_init(index_in);
 
  215    void other_init(
int index_in) {
 
  217      NN_dist = BJ::geometrical_beam_distance();
 
  220    int jet_index()
 const {
return _index;}
 
  223    TiledJet * NN, *previous, * next;
 
  224    int tile_index, diJ_posn;
 
  229    inline void label_minheap_update_needed() {diJ_posn = 1;}
 
  230    inline void label_minheap_update_done()   {diJ_posn = 0;}
 
  231    inline bool minheap_update_needed()
 const {
return diJ_posn==1;}
 
  239  static const int n_tile_neighbours = 9;
 
  246    Tile *   begin_tiles[n_tile_neighbours]; 
 
  248    Tile **  surrounding_tiles; 
 
  260  class diJ_plus_link {
 
  274  _initialise_tiles(jets);
 
  278  briefjets = 
new TiledJet[n];
 
  279  where_is.resize(2*n);
 
  281  TiledJet * jetA = briefjets, * jetB;
 
  285  tile_union.resize(3*n_tile_neighbours);
 
  288  for (
int i = 0; i< n; i++) {
 
  289    _tiledjet_set_jetinfo(jetA, jets[i], i);
 
  297  typename std::vector<Tile>::const_iterator tile;
 
  298  for (tile = _tiles.begin(); tile != _tiles.end(); tile++) {
 
  300    for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
 
  301      for (jetB = tile->head; jetB != jetA; jetB = jetB->next) {
 
  302        double dist = jetA->geometrical_distance(jetB);
 
  303        if (dist < jetA->NN_dist) {jetA->NN_dist = dist; jetA->NN = jetB;}
 
  304        if (dist < jetB->NN_dist) {jetB->NN_dist = dist; jetB->NN = jetA;}
 
  308    for (Tile ** RTile = tile->RH_tiles; RTile != tile->end_tiles; RTile++) {
 
  309      for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
 
  310        for (jetB = (*RTile)->head; jetB != NULL; jetB = jetB->next) {
 
  311          double dist = jetA->geometrical_distance(jetB);
 
  312          if (dist < jetA->NN_dist) {jetA->NN_dist = dist; jetA->NN = jetB;}
 
  313          if (dist < jetB->NN_dist) {jetB->NN_dist = dist; jetB->NN = jetA;}
 
  321  diJ = 
new diJ_plus_link[n];
 
  323  for (
int i = 0; i < n; i++) {
 
  324    diJ[i].diJ = _compute_diJ(jetA); 
 
  336  diJ_plus_link * best, *stop; 
 
  342  double diJ_min = diJ[0].diJ; 
 
  345  for (diJ_plus_link * here = diJ+1; here != stop; here++) {
 
  346    if (here->diJ < diJ_min) {best = here; diJ_min  = here->diJ;}
 
  350  TiledJet * jetA = best->jet;
 
  351  iA = jetA->jet_index();
 
  352  iB = jetA->NN ? jetA->NN->jet_index() : -1;
 
  360  TiledJet * jetA = where_is[iA];
 
  362  _bj_remove_from_tiles(jetA);
 
  368  int n_near_tiles = 0;
 
  369  _add_untagged_neighbours_to_tile_union(jetA->tile_index, n_near_tiles);
 
  376  diJ[n].jet->diJ_posn = jetA->diJ_posn;
 
  377  diJ[jetA->diJ_posn] = diJ[n];
 
  381  for (
int itile = 0; itile < n_near_tiles; itile++) {
 
  382    Tile * tile_ptr = &_tiles[tile_union[itile]];
 
  383    tile_ptr->tagged = 
false; 
 
  385    for (TiledJet * jetI = tile_ptr->head; jetI != NULL; jetI = jetI->next) {
 
  387      if (jetI->NN == jetA) {
 
  388        jetI->NN_dist = jetI->geometrical_beam_distance();
 
  391        for (Tile ** near_tile  = tile_ptr->begin_tiles; 
 
  392             near_tile != tile_ptr->end_tiles; near_tile++) {
 
  394          for (TiledJet * jetJ  = (*near_tile)->head; jetJ != NULL; jetJ = jetJ->next) {
 
  395            double dist = jetI->geometrical_distance(jetJ);
 
  396            if (dist < jetI->NN_dist && jetJ != jetI) {
 
  397              jetI->NN_dist = dist; jetI->NN = jetJ;
 
  401        diJ[jetI->diJ_posn].diJ = _compute_diJ(jetI); 
 
  413  TiledJet * jetA = where_is[iA];
 
  414  TiledJet * jetB = where_is[iB];
 
  421  if (jetA < jetB) {std::swap(jetA,jetB);}
 
  424  _bj_remove_from_tiles(jetA);
 
  425  TiledJet oldB = * jetB;  
 
  426  _bj_remove_from_tiles(jetB);
 
  427  _tiledjet_set_jetinfo(jetB, jet, index); 
 
  429  where_is[index] = jetB;
 
  435  int n_near_tiles = 0;
 
  436  _add_untagged_neighbours_to_tile_union(jetA->tile_index, n_near_tiles);
 
  437  if (jetB->tile_index != jetA->tile_index) {
 
  438    _add_untagged_neighbours_to_tile_union(jetB->tile_index, n_near_tiles);
 
  440  if (oldB.tile_index != jetA->tile_index && 
 
  441      oldB.tile_index != jetB->tile_index) {
 
  442    _add_untagged_neighbours_to_tile_union(oldB.tile_index, n_near_tiles);
 
  450  diJ[n].jet->diJ_posn = jetA->diJ_posn;
 
  451  diJ[jetA->diJ_posn] = diJ[n];
 
  456  for (
int itile = 0; itile < n_near_tiles; itile++) {
 
  457    Tile * tile_ptr = &_tiles[tile_union[itile]];
 
  458    tile_ptr->tagged = 
false; 
 
  460    for (TiledJet * jetI = tile_ptr->head; jetI != NULL; jetI = jetI->next) {
 
  462      if ((jetI->NN == jetA) || (jetI->NN == jetB)) {
 
  463        jetI->NN_dist = jetI->geometrical_beam_distance();
 
  466        for (Tile ** near_tile  = tile_ptr->begin_tiles; near_tile != tile_ptr->end_tiles; near_tile++) {
 
  468          for (TiledJet * jetJ  = (*near_tile)->head; jetJ != NULL; jetJ = jetJ->next) {
 
  469            double dist = jetI->geometrical_distance(jetJ);
 
  470            if (dist < jetI->NN_dist && jetJ != jetI) {
 
  471              jetI->NN_dist = dist; jetI->NN = jetJ;
 
  475        diJ[jetI->diJ_posn].diJ = _compute_diJ(jetI); 
 
  480      double dist = jetI->geometrical_distance(jetB);
 
  481      if (dist < jetI->NN_dist) {
 
  483          jetI->NN_dist = dist;
 
  485          diJ[jetI->diJ_posn].diJ = _compute_diJ(jetI); 
 
  488      if (dist < jetB->NN_dist) {
 
  490          jetB->NN_dist = dist;
 
  497  diJ[jetB->diJ_posn].diJ = _compute_diJ(jetB);
 
  520template <
class BJ, 
class I>
 
  525  double default_size = _requested_tile_size>0.1 ? _requested_tile_size : 0.1;
 
  526  _tile_size_rap = default_size;
 
  530  _n_tiles_phi   = int(floor(twopi/default_size));
 
  531  if (_n_tiles_phi<3) _n_tiles_phi = 3;
 
  532  _tile_size_phi = twopi / _n_tiles_phi; 
 
  535  _tiles_rap_min = tiling_analysis.minrap();
 
  536  _tiles_rap_max = tiling_analysis.maxrap();
 
  539  _tiles_irap_min = int(floor(_tiles_rap_min/_tile_size_rap));
 
  540  _tiles_irap_max = int(floor( _tiles_rap_max/_tile_size_rap));
 
  541  _tiles_rap_min = _tiles_irap_min * _tile_size_rap;
 
  542  _tiles_rap_max = _tiles_irap_max * _tile_size_rap;
 
  545  _tiles.resize((_tiles_irap_max-_tiles_irap_min+1)*_n_tiles_phi);
 
  548  for (
int irap = _tiles_irap_min; irap <= _tiles_irap_max; irap++) {
 
  549    for (
int iphi = 0; iphi < _n_tiles_phi; iphi++) {
 
  550      Tile * tile = & _tiles[_tile_index(irap,iphi)];
 
  553      tile->begin_tiles[0] =  tile;
 
  554      Tile ** pptile = & (tile->begin_tiles[0]);
 
  558      tile->surrounding_tiles = pptile;
 
  559      if (irap > _tiles_irap_min) {
 
  563        for (
int idphi = -1; idphi <=+1; idphi++) {
 
  564          *pptile = & _tiles[_tile_index(irap-1,iphi+idphi)];
 
  569      *pptile = & _tiles[_tile_index(irap,iphi-1)];
 
  572      tile->RH_tiles = pptile;
 
  573      *pptile = & _tiles[_tile_index(irap,iphi+1)];
 
  576      if (irap < _tiles_irap_max) {
 
  577        for (
int idphi = -1; idphi <= +1; idphi++) {
 
  578          *pptile = & _tiles[_tile_index(irap+1,iphi+idphi)];
 
  583      tile->end_tiles = pptile;
 
  585      tile->tagged = 
false;
 
  593template <
class BJ, 
class I>
 
  594int NNFJN2Tiled<BJ,I>::_tile_index(
const double rap, 
const double phi)
 const {
 
  596  if      (rap <= _tiles_rap_min) {irap = 0;}
 
  597  else if (rap >= _tiles_rap_max) {irap = _tiles_irap_max-_tiles_irap_min;}
 
  600    irap = int(((rap - _tiles_rap_min) / _tile_size_rap));
 
  602    if (irap > _tiles_irap_max-_tiles_irap_min) {
 
  603      irap = _tiles_irap_max-_tiles_irap_min;} 
 
  609  iphi = int((phi+twopi)/_tile_size_phi) % _n_tiles_phi;
 
  610  return (iphi + irap * _n_tiles_phi);
 
  614template <
class BJ, 
class I>
 
  615void NNFJN2Tiled<BJ,I>::_bj_remove_from_tiles(TiledJet * 
const jet) {
 
  616  Tile * tile = & _tiles[jet->tile_index];
 
  618  if (jet->previous == NULL) {
 
  621    tile->head = jet->next;
 
  624    jet->previous->next = jet->next;
 
  626  if (jet->next != NULL) {
 
  628    jet->next->previous = jet->previous;
 
  636template <
class BJ, 
class I>
 
  637inline void NNFJN2Tiled<BJ,I>::_tiledjet_set_jetinfo(TiledJet * 
const tile_jet,
 
  638                                                   const PseudoJet &jet, 
 
  642  this->init_jet(tile_jet, jet, index); 
 
  647  tile_jet->tile_index = _tile_index(tile_jet->rap(), tile_jet->phi());
 
  650  Tile * tile = &_tiles[tile_jet->tile_index];
 
  651  tile_jet->previous   = NULL;
 
  652  tile_jet->next       = tile->head;
 
  653  if (tile_jet->next != NULL) {tile_jet->next->previous = tile_jet;}
 
  654  tile->head      = tile_jet;
 
  664template <
class BJ, 
class I>
 
  665void NNFJN2Tiled<BJ,I>::_add_neighbours_to_tile_union(
const int tile_index, 
 
  666                                                    int & n_near_tiles)
 const {
 
  667  for (Tile * 
const * near_tile = _tiles[tile_index].begin_tiles; 
 
  668       near_tile != _tiles[tile_index].end_tiles; near_tile++){
 
  670    tile_union[n_near_tiles] = *near_tile - & _tiles[0];
 
  696template <
class BJ, 
class I>
 
  697inline void NNFJN2Tiled<BJ,I>::_add_untagged_neighbours_to_tile_union(
 
  698               const int tile_index, 
 
  699               int & n_near_tiles)  {
 
  700  for (Tile ** near_tile = _tiles[tile_index].begin_tiles; 
 
  701       near_tile != _tiles[tile_index].end_tiles; near_tile++){
 
  702    if (! (*near_tile)->tagged) {
 
  703      (*near_tile)->tagged = 
true;
 
  705      tile_union[n_near_tiles] = *near_tile - & _tiles[0];
 
Helps solve closest pair problems with generic interparticle and particle-beam distances.
 
Helps solve closest pair problems with factorised interparticle and beam distances (ie satisfying the...
 
NNFJN2Tiled(const std::vector< PseudoJet > &jets, double requested_tile_size)
constructor with an initial set of jets (which will be assigned indices 0...jets.size()-1)
 
~NNFJN2Tiled()
a destructor
 
Class to contain pseudojets, including minimal information of use to jet-clustering routines.
 
structure analogous to BriefJet, but with the extra information needed for dealing with tiles
 
class to perform a fast analysis of the appropriate rapidity range in which to perform tiling