File indexing completed on 2025-01-18 09:57:18
0001 #ifndef __FASTJET_NNFJN2TILED_HH__
0002 #define __FASTJET_NNFJN2TILED_HH__
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034 #include "fastjet/NNBase.hh"
0035 #include "fastjet/internal/TilingExtent.hh"
0036
0037 FASTJET_BEGIN_NAMESPACE
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097
0098
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113 template<class BJ, class I = _NoInfo> class NNFJN2Tiled : public NNBase<I> {
0114 public:
0115
0116
0117
0118 NNFJN2Tiled(const std::vector<PseudoJet> & jets, double requested_tile_size)
0119 : NNBase<I>(), _requested_tile_size(requested_tile_size) {start(jets);}
0120 NNFJN2Tiled(const std::vector<PseudoJet> & jets, double requested_tile_size, I * info)
0121 : NNBase<I>(info), _requested_tile_size(requested_tile_size) {start(jets);}
0122
0123 void start(const std::vector<PseudoJet> & jets);
0124
0125
0126
0127 double dij_min(int & iA, int & iB);
0128
0129
0130 void remove_jet(int iA);
0131
0132
0133
0134 void merge_jets(int iA, int iB, const PseudoJet & jet, int jet_index);
0135
0136
0137 ~NNFJN2Tiled() {
0138 delete[] briefjets;
0139 delete[] diJ;
0140 }
0141
0142 private:
0143 class TiledJet;
0144 class Tile;
0145 class diJ_plus_link;
0146
0147
0148 void _initialise_tiles(const std::vector<PseudoJet> & particles);
0149
0150
0151 inline double _compute_diJ(const TiledJet * const jet) const {
0152 double mom_fact = jet->momentum_factor();
0153 if (jet->NN != NULL) {
0154 double other_mom_fact = jet->NN->momentum_factor();
0155 if (other_mom_fact < mom_fact) {mom_fact = other_mom_fact;}
0156 }
0157 return jet->NN_dist * mom_fact;
0158 }
0159
0160
0161
0162 inline int _tile_index (int irap, int iphi) const {
0163
0164
0165 return (irap-_tiles_irap_min)*_n_tiles_phi
0166 + (iphi+_n_tiles_phi) % _n_tiles_phi;
0167 }
0168
0169 int _tile_index(const double rap, const double phi) const;
0170 void _tiledjet_set_jetinfo ( TiledJet * const tiled_jet, const PseudoJet &jet, int index);
0171 void _bj_remove_from_tiles(TiledJet * const jet);
0172 void _initialise_tiles();
0173 void _print_tiles(TiledJet * briefjets ) const;
0174 void _add_neighbours_to_tile_union(const int tile_index, int & n_near_tiles) const;
0175 void _add_untagged_neighbours_to_tile_union(const int tile_index, int & n_near_tiles);
0176
0177
0178
0179 TiledJet * briefjets;
0180
0181
0182 TiledJet * head;
0183
0184
0185 int n;
0186
0187
0188 std::vector<TiledJet *> where_is;
0189
0190
0191 std::vector<int> tile_union;
0192
0193
0194 diJ_plus_link * diJ;
0195
0196
0197 std::vector<Tile> _tiles;
0198 double _requested_tile_size;
0199 double _tiles_rap_min, _tiles_rap_max;
0200 double _tile_size_rap, _tile_size_phi;
0201 int _n_tiles_phi,_tiles_irap_min,_tiles_irap_max;
0202
0203
0204
0205 class TiledJet : public BJ {
0206 public:
0207 void init(const PseudoJet & jet, int index_in) {
0208 BJ::init(jet);
0209 other_init(index_in);
0210 }
0211 void init(const PseudoJet & jet, int index_in, I * info) {
0212 BJ::init(jet, info);
0213 other_init(index_in);
0214 }
0215 void other_init(int index_in) {
0216 _index = index_in;
0217 NN_dist = BJ::geometrical_beam_distance();
0218 NN = NULL;
0219 }
0220 int jet_index() const {return _index;}
0221
0222 double NN_dist;
0223 TiledJet * NN, *previous, * next;
0224 int tile_index, diJ_posn;
0225
0226
0227
0228
0229 inline void label_minheap_update_needed() {diJ_posn = 1;}
0230 inline void label_minheap_update_done() {diJ_posn = 0;}
0231 inline bool minheap_update_needed() const {return diJ_posn==1;}
0232
0233 private:
0234 int _index;
0235 };
0236
0237
0238
0239 static const int n_tile_neighbours = 9;
0240
0241
0242
0243 class Tile {
0244 public:
0245
0246 Tile * begin_tiles[n_tile_neighbours];
0247
0248 Tile ** surrounding_tiles;
0249
0250 Tile ** RH_tiles;
0251
0252 Tile ** end_tiles;
0253
0254 TiledJet * head;
0255
0256 bool tagged;
0257 };
0258
0259
0260 class diJ_plus_link {
0261 public:
0262 double diJ;
0263 TiledJet * jet;
0264
0265 };
0266
0267 };
0268
0269
0270
0271
0272 template<class BJ, class I> void NNFJN2Tiled<BJ,I>::start(const std::vector<PseudoJet> & jets) {
0273
0274 _initialise_tiles(jets);
0275
0276 n = jets.size();
0277
0278 briefjets = new TiledJet[n];
0279 where_is.resize(2*n);
0280
0281 TiledJet * jetA = briefjets, * jetB;
0282
0283
0284
0285 tile_union.resize(3*n_tile_neighbours);
0286
0287
0288 for (int i = 0; i< n; i++) {
0289 _tiledjet_set_jetinfo(jetA, jets[i], i);
0290 where_is[i] = jetA;
0291 jetA++;
0292 }
0293
0294 head = briefjets;
0295
0296
0297 typename std::vector<Tile>::const_iterator tile;
0298 for (tile = _tiles.begin(); tile != _tiles.end(); tile++) {
0299
0300 for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
0301 for (jetB = tile->head; jetB != jetA; jetB = jetB->next) {
0302 double dist = jetA->geometrical_distance(jetB);
0303 if (dist < jetA->NN_dist) {jetA->NN_dist = dist; jetA->NN = jetB;}
0304 if (dist < jetB->NN_dist) {jetB->NN_dist = dist; jetB->NN = jetA;}
0305 }
0306 }
0307
0308 for (Tile ** RTile = tile->RH_tiles; RTile != tile->end_tiles; RTile++) {
0309 for (jetA = tile->head; jetA != NULL; jetA = jetA->next) {
0310 for (jetB = (*RTile)->head; jetB != NULL; jetB = jetB->next) {
0311 double dist = jetA->geometrical_distance(jetB);
0312 if (dist < jetA->NN_dist) {jetA->NN_dist = dist; jetA->NN = jetB;}
0313 if (dist < jetB->NN_dist) {jetB->NN_dist = dist; jetB->NN = jetA;}
0314 }
0315 }
0316 }
0317
0318
0319 }
0320
0321 diJ = new diJ_plus_link[n];
0322 jetA = head;
0323 for (int i = 0; i < n; i++) {
0324 diJ[i].diJ = _compute_diJ(jetA);
0325 diJ[i].jet = jetA;
0326 jetA->diJ_posn = i;
0327
0328 jetA++;
0329 }
0330 }
0331
0332
0333
0334 template<class BJ, class I> double NNFJN2Tiled<BJ,I>::dij_min(int & iA, int & iB) {
0335
0336 diJ_plus_link * best, *stop;
0337
0338
0339
0340
0341
0342 double diJ_min = diJ[0].diJ;
0343 best = diJ;
0344 stop = diJ+n;
0345 for (diJ_plus_link * here = diJ+1; here != stop; here++) {
0346 if (here->diJ < diJ_min) {best = here; diJ_min = here->diJ;}
0347 }
0348
0349
0350 TiledJet * jetA = best->jet;
0351 iA = jetA->jet_index();
0352 iB = jetA->NN ? jetA->NN->jet_index() : -1;
0353 return diJ_min;
0354 }
0355
0356
0357
0358
0359 template<class BJ, class I> void NNFJN2Tiled<BJ,I>::remove_jet(int iA) {
0360 TiledJet * jetA = where_is[iA];
0361
0362 _bj_remove_from_tiles(jetA);
0363
0364
0365
0366
0367
0368 int n_near_tiles = 0;
0369 _add_untagged_neighbours_to_tile_union(jetA->tile_index, n_near_tiles);
0370
0371
0372
0373 n--;
0374
0375
0376 diJ[n].jet->diJ_posn = jetA->diJ_posn;
0377 diJ[jetA->diJ_posn] = diJ[n];
0378
0379
0380
0381 for (int itile = 0; itile < n_near_tiles; itile++) {
0382 Tile * tile_ptr = &_tiles[tile_union[itile]];
0383 tile_ptr->tagged = false;
0384
0385 for (TiledJet * jetI = tile_ptr->head; jetI != NULL; jetI = jetI->next) {
0386
0387 if (jetI->NN == jetA) {
0388 jetI->NN_dist = jetI->geometrical_beam_distance();
0389 jetI->NN = NULL;
0390
0391 for (Tile ** near_tile = tile_ptr->begin_tiles;
0392 near_tile != tile_ptr->end_tiles; near_tile++) {
0393
0394 for (TiledJet * jetJ = (*near_tile)->head; jetJ != NULL; jetJ = jetJ->next) {
0395 double dist = jetI->geometrical_distance(jetJ);
0396 if (dist < jetI->NN_dist && jetJ != jetI) {
0397 jetI->NN_dist = dist; jetI->NN = jetJ;
0398 }
0399 }
0400 }
0401 diJ[jetI->diJ_posn].diJ = _compute_diJ(jetI);
0402 }
0403 }
0404 }
0405
0406 }
0407
0408
0409
0410 template<class BJ, class I> void NNFJN2Tiled<BJ,I>::merge_jets(int iA, int iB,
0411 const PseudoJet & jet, int index) {
0412
0413 TiledJet * jetA = where_is[iA];
0414 TiledJet * jetB = where_is[iB];
0415
0416
0417
0418
0419
0420
0421 if (jetA < jetB) {std::swap(jetA,jetB);}
0422
0423
0424 _bj_remove_from_tiles(jetA);
0425 TiledJet oldB = * jetB;
0426 _bj_remove_from_tiles(jetB);
0427 _tiledjet_set_jetinfo(jetB, jet, index);
0428
0429 where_is[index] = jetB;
0430
0431
0432
0433
0434
0435 int n_near_tiles = 0;
0436 _add_untagged_neighbours_to_tile_union(jetA->tile_index, n_near_tiles);
0437 if (jetB->tile_index != jetA->tile_index) {
0438 _add_untagged_neighbours_to_tile_union(jetB->tile_index, n_near_tiles);
0439 }
0440 if (oldB.tile_index != jetA->tile_index &&
0441 oldB.tile_index != jetB->tile_index) {
0442 _add_untagged_neighbours_to_tile_union(oldB.tile_index, n_near_tiles);
0443 }
0444
0445
0446
0447 n--;
0448
0449
0450 diJ[n].jet->diJ_posn = jetA->diJ_posn;
0451 diJ[jetA->diJ_posn] = diJ[n];
0452
0453
0454
0455
0456 for (int itile = 0; itile < n_near_tiles; itile++) {
0457 Tile * tile_ptr = &_tiles[tile_union[itile]];
0458 tile_ptr->tagged = false;
0459
0460 for (TiledJet * jetI = tile_ptr->head; jetI != NULL; jetI = jetI->next) {
0461
0462 if ((jetI->NN == jetA) || (jetI->NN == jetB)) {
0463 jetI->NN_dist = jetI->geometrical_beam_distance();
0464 jetI->NN = NULL;
0465
0466 for (Tile ** near_tile = tile_ptr->begin_tiles; near_tile != tile_ptr->end_tiles; near_tile++) {
0467
0468 for (TiledJet * jetJ = (*near_tile)->head; jetJ != NULL; jetJ = jetJ->next) {
0469 double dist = jetI->geometrical_distance(jetJ);
0470 if (dist < jetI->NN_dist && jetJ != jetI) {
0471 jetI->NN_dist = dist; jetI->NN = jetJ;
0472 }
0473 }
0474 }
0475 diJ[jetI->diJ_posn].diJ = _compute_diJ(jetI);
0476 }
0477
0478
0479
0480 double dist = jetI->geometrical_distance(jetB);
0481 if (dist < jetI->NN_dist) {
0482 if (jetI != jetB) {
0483 jetI->NN_dist = dist;
0484 jetI->NN = jetB;
0485 diJ[jetI->diJ_posn].diJ = _compute_diJ(jetI);
0486 }
0487 }
0488 if (dist < jetB->NN_dist) {
0489 if (jetI != jetB) {
0490 jetB->NN_dist = dist;
0491 jetB->NN = jetI;}
0492 }
0493 }
0494 }
0495
0496
0497 diJ[jetB->diJ_posn].diJ = _compute_diJ(jetB);
0498 }
0499
0500
0501
0502
0503
0504
0505
0506
0507
0508
0509
0510
0511
0512
0513
0514
0515
0516
0517
0518
0519
0520 template <class BJ, class I>
0521 void NNFJN2Tiled<BJ,I>::_initialise_tiles(const std::vector<PseudoJet> &particles) {
0522
0523
0524
0525 double default_size = _requested_tile_size>0.1 ? _requested_tile_size : 0.1;
0526 _tile_size_rap = default_size;
0527
0528
0529
0530 _n_tiles_phi = int(floor(twopi/default_size));
0531 if (_n_tiles_phi<3) _n_tiles_phi = 3;
0532 _tile_size_phi = twopi / _n_tiles_phi;
0533
0534 TilingExtent tiling_analysis(particles);
0535 _tiles_rap_min = tiling_analysis.minrap();
0536 _tiles_rap_max = tiling_analysis.maxrap();
0537
0538
0539 _tiles_irap_min = int(floor(_tiles_rap_min/_tile_size_rap));
0540 _tiles_irap_max = int(floor( _tiles_rap_max/_tile_size_rap));
0541 _tiles_rap_min = _tiles_irap_min * _tile_size_rap;
0542 _tiles_rap_max = _tiles_irap_max * _tile_size_rap;
0543
0544
0545 _tiles.resize((_tiles_irap_max-_tiles_irap_min+1)*_n_tiles_phi);
0546
0547
0548 for (int irap = _tiles_irap_min; irap <= _tiles_irap_max; irap++) {
0549 for (int iphi = 0; iphi < _n_tiles_phi; iphi++) {
0550 Tile * tile = & _tiles[_tile_index(irap,iphi)];
0551
0552 tile->head = NULL;
0553 tile->begin_tiles[0] = tile;
0554 Tile ** pptile = & (tile->begin_tiles[0]);
0555 pptile++;
0556
0557
0558 tile->surrounding_tiles = pptile;
0559 if (irap > _tiles_irap_min) {
0560
0561
0562
0563 for (int idphi = -1; idphi <=+1; idphi++) {
0564 *pptile = & _tiles[_tile_index(irap-1,iphi+idphi)];
0565 pptile++;
0566 }
0567 }
0568
0569 *pptile = & _tiles[_tile_index(irap,iphi-1)];
0570 pptile++;
0571
0572 tile->RH_tiles = pptile;
0573 *pptile = & _tiles[_tile_index(irap,iphi+1)];
0574 pptile++;
0575
0576 if (irap < _tiles_irap_max) {
0577 for (int idphi = -1; idphi <= +1; idphi++) {
0578 *pptile = & _tiles[_tile_index(irap+1,iphi+idphi)];
0579 pptile++;
0580 }
0581 }
0582
0583 tile->end_tiles = pptile;
0584
0585 tile->tagged = false;
0586 }
0587 }
0588
0589 }
0590
0591
0592
0593 template <class BJ, class I>
0594 int NNFJN2Tiled<BJ,I>::_tile_index(const double rap, const double phi) const {
0595 int irap, iphi;
0596 if (rap <= _tiles_rap_min) {irap = 0;}
0597 else if (rap >= _tiles_rap_max) {irap = _tiles_irap_max-_tiles_irap_min;}
0598 else {
0599
0600 irap = int(((rap - _tiles_rap_min) / _tile_size_rap));
0601
0602 if (irap > _tiles_irap_max-_tiles_irap_min) {
0603 irap = _tiles_irap_max-_tiles_irap_min;}
0604 }
0605
0606
0607
0608
0609 iphi = int((phi+twopi)/_tile_size_phi) % _n_tiles_phi;
0610 return (iphi + irap * _n_tiles_phi);
0611 }
0612
0613
0614 template <class BJ, class I>
0615 void NNFJN2Tiled<BJ,I>::_bj_remove_from_tiles(TiledJet * const jet) {
0616 Tile * tile = & _tiles[jet->tile_index];
0617
0618 if (jet->previous == NULL) {
0619
0620
0621 tile->head = jet->next;
0622 } else {
0623
0624 jet->previous->next = jet->next;
0625 }
0626 if (jet->next != NULL) {
0627
0628 jet->next->previous = jet->previous;
0629 }
0630 }
0631
0632
0633
0634
0635
0636 template <class BJ, class I>
0637 inline void NNFJN2Tiled<BJ,I>::_tiledjet_set_jetinfo(TiledJet * const tile_jet,
0638 const PseudoJet &jet,
0639 int index) {
0640
0641
0642 this->init_jet(tile_jet, jet, index);
0643
0644
0645
0646
0647 tile_jet->tile_index = _tile_index(tile_jet->rap(), tile_jet->phi());
0648
0649
0650 Tile * tile = &_tiles[tile_jet->tile_index];
0651 tile_jet->previous = NULL;
0652 tile_jet->next = tile->head;
0653 if (tile_jet->next != NULL) {tile_jet->next->previous = tile_jet;}
0654 tile->head = tile_jet;
0655 }
0656
0657
0658
0659
0660
0661
0662
0663
0664 template <class BJ, class I>
0665 void NNFJN2Tiled<BJ,I>::_add_neighbours_to_tile_union(const int tile_index,
0666 int & n_near_tiles) const {
0667 for (Tile * const * near_tile = _tiles[tile_index].begin_tiles;
0668 near_tile != _tiles[tile_index].end_tiles; near_tile++){
0669
0670 tile_union[n_near_tiles] = *near_tile - & _tiles[0];
0671 n_near_tiles++;
0672 }
0673 }
0674
0675
0676
0677
0678
0679
0680
0681
0682
0683
0684
0685
0686
0687
0688
0689
0690
0691
0692
0693
0694
0695
0696 template <class BJ, class I>
0697 inline void NNFJN2Tiled<BJ,I>::_add_untagged_neighbours_to_tile_union(
0698 const int tile_index,
0699 int & n_near_tiles) {
0700 for (Tile ** near_tile = _tiles[tile_index].begin_tiles;
0701 near_tile != _tiles[tile_index].end_tiles; near_tile++){
0702 if (! (*near_tile)->tagged) {
0703 (*near_tile)->tagged = true;
0704
0705 tile_union[n_near_tiles] = *near_tile - & _tiles[0];
0706 n_near_tiles++;
0707 }
0708 }
0709 }
0710
0711
0712
0713 FASTJET_END_NAMESPACE
0714
0715
0716 #endif