00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00026
00027 #include "split_merge.h"
00028 #include "siscone_error.h"
00029 #include "momentum.h"
00030 #include <math.h>
00031 #include <limits>
00032 #include <iostream>
00033 #include <algorithm>
00034 #include <sstream>
00035 #include <cassert>
00036
00037 namespace siscone{
00038
00039 using namespace std;
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051 Cjet::Cjet(){
00052 n = 0;
00053 v = Cmomentum();
00054 pt_tilde = 0.0;
00055 sm_var2 = 0.0;
00056 }
00057
00058
00059
00060 Cjet::~Cjet(){
00061
00062 }
00063
00064
00065
00066 bool jets_pt_less(const Cjet &j1, const Cjet &j2){
00067 return j1.v.perp2() > j2.v.perp2();
00068 }
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092 bool Csplit_merge_ptcomparison::operator ()(const Cjet &jet1, const Cjet &jet2) const{
00093 double q1, q2;
00094
00095
00096
00097 q1 = jet1.sm_var2;
00098 q2 = jet2.sm_var2;
00099
00100 bool res = q1 > q2;
00101
00102
00103
00104
00105 #ifdef EPSILON_SPLITMERGE
00106 if ( (fabs(q1-q2) < EPSILON_SPLITMERGE*max(q1,q2)) &&
00107 (jet1.v.ref != jet2.v.ref) ) {
00108
00109 Cmomentum difference;
00110 double pt_tilde_difference;
00111 get_difference(jet1,jet2,&difference,&pt_tilde_difference);
00112
00113
00114 double qdiff;
00115 Cmomentum sum = jet1.v ;
00116 sum += jet2.v;
00117 double pt_tilde_sum = jet1.pt_tilde + jet2.pt_tilde;
00118
00119
00120 switch (split_merge_scale){
00121 case SM_mt:
00122 qdiff = sum.E*difference.E - sum.pz*difference.pz;
00123 break;
00124 case SM_pt:
00125 qdiff = sum.px*difference.px + sum.py*difference.py;
00126 break;
00127 case SM_pttilde:
00128 qdiff = pt_tilde_sum*pt_tilde_difference;
00129 break;
00130 case SM_Et:
00131
00132
00133
00134
00135 qdiff = jet1.v.E*jet1.v.E*
00136 ((sum.px*difference.px + sum.py*difference.py)*jet1.v.pz*jet1.v.pz
00137 -jet1.v.perp2()*sum.pz*difference.pz)
00138 +sum.E*difference.E*(jet1.v.perp2()+jet1.v.pz*jet1.v.pz)*jet2.v.perp2();
00139 break;
00140 default:
00141 throw Csiscone_error("Unsupported split-merge scale choice: "
00142 + SM_scale_name());
00143 }
00144 res = qdiff > 0;
00145 }
00146 #endif // EPSILON_SPLITMERGE
00147
00148 return res;
00149 }
00150
00151
00154 std::string split_merge_scale_name(Esplit_merge_scale sms) {
00155 switch(sms) {
00156 case SM_pt:
00157 return "pt (IR unsafe)";
00158 case SM_Et:
00159 return "Et (boost dep.)";
00160 case SM_mt:
00161 return "mt (IR safe except for pairs of identical decayed heavy particles)";
00162 case SM_pttilde:
00163 return "pttilde (scalar sum of pt's)";
00164 default:
00165 return "[SM scale without a name]";
00166 }
00167 }
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177 void Csplit_merge_ptcomparison::get_difference(const Cjet &j1, const Cjet &j2, Cmomentum *v, double *pt_tilde) const {
00178 int i1,i2;
00179
00180
00181 i1=i2=0;
00182 *v = Cmomentum();
00183 *pt_tilde = 0.0;
00184
00185
00186
00187 do{
00188 if (j1.contents[i1]==j2.contents[i2]) {
00189 i1++;
00190 i2++;
00191 } else if (j1.contents[i1]<j2.contents[i2]){
00192 (*v) += (*particles)[j1.contents[i1]];
00193 (*pt_tilde) += (*pt)[j1.contents[i1]];
00194 i1++;
00195 } else if (j1.contents[i1]>j2.contents[i2]){
00196 (*v) -= (*particles)[j2.contents[i2]];
00197 (*pt_tilde) -= (*pt)[j2.contents[i2]];
00198 i2++;
00199 } else {
00200 throw Csiscone_error("get_non_overlap reached part it should never have seen...");
00201 }
00202 } while ((i1<j1.n) && (i2<j2.n));
00203
00204
00205 while (i1 < j1.n) {
00206 (*v) += (*particles)[j1.contents[i1]];
00207 (*pt_tilde) += (*pt)[j1.contents[i1]];
00208 i1++;
00209 }
00210 while (i2 < j2.n) {
00211 (*v) -= (*particles)[j2.contents[i2]];
00212 (*pt_tilde) -= (*pt)[j2.contents[i2]];
00213 i2++;
00214 }
00215 }
00216
00217
00218
00219
00220
00221
00222
00223
00224 Csplit_merge::Csplit_merge(){
00225 merge_identical_protocones = false;
00226 #ifdef ALLOW_MERGE_IDENTICAL_PROTOCONES
00227 #ifdef MERGE_IDENTICAL_PROTOCONES_DEFAULT_TRUE
00228 merge_identical_protocones = true;
00229 #endif
00230 #endif
00231 indices = NULL;
00232
00233
00234 ptcomparison.particles = &particles;
00235 ptcomparison.pt = &pt;
00236 candidates.reset(new multiset<Cjet,Csplit_merge_ptcomparison>(ptcomparison));
00237
00238
00239 SM_var2_hardest_cut_off = -1.0;
00240
00241
00242 stable_cone_soft_pt2_cutoff = -1.0;
00243 }
00244
00245
00246
00247
00248 Csplit_merge::~Csplit_merge(){
00249 full_clear();
00250 }
00251
00252
00253
00254
00255
00256
00257
00258
00259 int Csplit_merge::init(vector<Cmomentum> &_particles, vector<Cmomentum> *protocones, double R2, double ptmin){
00260
00261 return add_protocones(protocones, R2, ptmin);
00262 }
00263
00264
00265
00266
00267
00268 int Csplit_merge::init_particles(vector<Cmomentum> &_particles){
00269 full_clear();
00270
00271
00272
00273
00274 particles = _particles;
00275 n = particles.size();
00276
00277
00278 double eta_min=0.0;
00279 double eta_max=0.0;
00280 pt.resize(n);
00281 for (int i=0;i<n;i++){
00282 pt[i] = particles[i].perp();
00283 eta_min = min(eta_min, particles[i].eta);
00284 eta_max = max(eta_max, particles[i].eta);
00285 }
00286 Ceta_phi_range epr;
00287 epr.eta_min = eta_min-0.01;
00288 epr.eta_max = eta_max+0.01;
00289
00290
00291 ptcomparison.particles = &particles;
00292 ptcomparison.pt = &pt;
00293
00294
00295 init_pleft();
00296
00297 indices = new int[n];
00298
00299 return 0;
00300 }
00301
00302
00303
00304
00305 int Csplit_merge::init_pleft(){
00306
00307
00308
00309
00310
00311
00312
00313 int i,j;
00314
00315
00316 j=0;
00317 p_remain.clear();
00318 for (i=0;i<n;i++){
00319
00320 particles[i].ref.randomize();
00321
00322
00323 if (fabs(particles[i].pz) < (particles[i].E)){
00324 p_remain.push_back(particles[i]);
00325
00326 p_remain[j].parent_index = i;
00327
00328
00329
00330
00331
00332
00333 p_remain[j].index = 1;
00334
00335 j++;
00336
00337 particles[i].index = 0;
00338 } else {
00339 particles[i].index = -1;
00340 }
00341 }
00342 n_left = p_remain.size();
00343 n_pass = 0;
00344
00345 merge_collinear_and_remove_soft();
00346
00347 return 0;
00348 }
00349
00350
00351
00352
00353
00354
00355
00356 int Csplit_merge::partial_clear(){
00357
00358
00359
00360
00361
00362 candidates.reset(new multiset<Cjet,Csplit_merge_ptcomparison>(ptcomparison));
00363
00364
00365 most_ambiguous_split = numeric_limits<double>::max();
00366
00367 jets.clear();
00368 #ifdef ALLOW_MERGE_IDENTICAL_PROTOCONES
00369 if (merge_identical_protocones)
00370 cand_refs.clear();
00371 #endif
00372
00373 p_remain.clear();
00374
00375 return 0;
00376 }
00377
00378
00379
00380
00381 int Csplit_merge::full_clear(){
00382 partial_clear();
00383
00384
00385 if (indices != NULL){
00386 delete[] indices;
00387 }
00388 particles.clear();
00389
00390 return 0;
00391 }
00392
00393
00394
00395
00396
00397
00398 int Csplit_merge::merge_collinear_and_remove_soft(){
00399 int i,j;
00400 vector<Cmomentum> p_sorted;
00401 bool collinear;
00402 double dphi;
00403
00404 p_uncol_hard.clear();
00405
00406
00407 for (i=0;i<n_left;i++)
00408 p_sorted.push_back(p_remain[i]);
00409 sort(p_sorted.begin(), p_sorted.end(), momentum_eta_less);
00410
00411
00412
00413
00414
00415 i = 0;
00416 while (i<n_left){
00417
00418 if (p_sorted[i].perp2()<stable_cone_soft_pt2_cutoff) {
00419 i++;
00420 continue;
00421 }
00422
00423
00424 collinear = false;
00425 j=i+1;
00426 while ((j<n_left) && (fabs(p_sorted[j].eta-p_sorted[i].eta)<EPSILON_COLLINEAR) && (!collinear)){
00427 dphi = fabs(p_sorted[j].phi-p_sorted[i].phi);
00428 if (dphi>M_PI) dphi = twopi-dphi;
00429 if (dphi<EPSILON_COLLINEAR){
00430
00431 p_sorted[j] += p_sorted[i];
00432
00433 collinear = true;
00434 }
00435 j++;
00436 }
00437
00438 if (!collinear)
00439 p_uncol_hard.push_back(p_sorted[i]);
00440 i++;
00441 }
00442
00443 return 0;
00444 }
00445
00446
00447
00448
00449
00450
00451
00452 int Csplit_merge::add_protocones(vector<Cmomentum> *protocones, double R2, double ptmin){
00453 int i;
00454 Cmomentum *c;
00455 Cmomentum *v;
00456 double eta, phi;
00457 double dx, dy;
00458 double R;
00459 Cjet jet;
00460
00461 if (protocones->size()==0)
00462 return 1;
00463
00464 pt_min2 = ptmin*ptmin;
00465 R = sqrt(R2);
00466
00467
00468
00469 for (vector<Cmomentum>::iterator p_it = protocones->begin();p_it != protocones->end();p_it++){
00470
00471 c = &(*p_it);
00472
00473
00474 eta = c->eta;
00475 phi = c->phi;
00476
00477
00478
00479 jet.v = Cmomentum();
00480 jet.pt_tilde=0;
00481 jet.contents.clear();
00482 for (i=0;i<n_left;i++){
00483 v = &(p_remain[i]);
00484
00485
00486
00487 dx = eta - v->eta;
00488 dy = fabs(phi - v->phi);
00489 if (dy>M_PI)
00490 dy -= twopi;
00491 if (dx*dx+dy*dy<R2){
00492 jet.contents.push_back(v->parent_index);
00493 jet.v+= *v;
00494 jet.pt_tilde+= pt[v->parent_index];
00495 v->index=0;
00496 }
00497 }
00498 jet.n=jet.contents.size();
00499
00500
00501
00502 *c = jet.v;
00503 c->eta = eta;
00504 c->phi = phi;
00505
00506
00507 jet.range=Ceta_phi_range(eta,phi,R);
00508
00509 #ifdef DEBUG_SPLIT_MERGE
00510 cout << "adding jet: ";
00511 for (int i2=0;i2<jet.n;i2++)
00512 cout << jet.contents[i2] << " ";
00513 cout << endl;
00514 #endif
00515
00516
00517 insert(jet);
00518 }
00519
00520
00521 n_pass++;
00522
00523 #ifdef DEBUG_SPLIT_MERGE
00524 cout << "remaining particles: ";
00525 #endif
00526 int j=0;
00527 for (i=0;i<n_left;i++){
00528 if (p_remain[i].index){
00529
00530 p_remain[j]=p_remain[i];
00531 p_remain[j].parent_index = p_remain[i].parent_index;
00532 p_remain[j].index=1;
00533
00534 particles[p_remain[j].parent_index].index = n_pass;
00535 #ifdef DEBUG_SPLIT_MERGE
00536 cout << p_remain[j].parent_index << " ";
00537 #endif
00538 j++;
00539 }
00540 }
00541 #ifdef DEBUG_SPLIT_MERGE
00542 cout << endl;
00543 #endif
00544 n_left = j;
00545 p_remain.resize(j);
00546
00547 merge_collinear_and_remove_soft();
00548
00549 return 0;
00550 }
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562 int Csplit_merge::perform(double overlap_tshold, double ptmin){
00563
00564 cjet_iterator j1;
00565 cjet_iterator j2;
00566
00567 pt_min2 = ptmin*ptmin;
00568
00569 if (candidates->size()==0)
00570 return 0;
00571
00572 if (overlap_tshold>=1.0 || overlap_tshold <= 0) {
00573 ostringstream message;
00574 message << "Illegal value for overlap_tshold, f = " << overlap_tshold;
00575 message << " (legal values are 0<f<1)";
00576 throw Csiscone_error(message.str());
00577 }
00578
00579
00580
00581
00582 double overlap2;
00583
00584
00585 double overlap_tshold2 = overlap_tshold*overlap_tshold;
00586
00587 do{
00588 if (candidates->size()>0){
00589
00590 j1 = candidates->begin();
00591
00592
00593
00594 if (j1->sm_var2<SM_var2_hardest_cut_off) {break;}
00595
00596
00597 j2 = j1;
00598 j2++;
00599 int j2_relindex = 1;
00600
00601 while (j2 != candidates->end()){
00602 #ifdef DEBUG_SPLIT_MERGE
00603 show();
00604 #endif
00605
00606 if (get_overlap(*j1, *j2, &overlap2)){
00607
00608
00609 #ifdef DEBUG_SPLIT_MERGE
00610 cout << "overlap between cdt 1 and cdt " << j2_relindex+1 << " with overlap "
00611 << sqrt(overlap2/j2->sm_var2) << endl<<endl;
00612 #endif
00613 if (overlap2<overlap_tshold2*j2->sm_var2){
00614
00615 split(j1, j2);
00616
00617
00618 j2 = j1 = candidates->begin();
00619 j2_relindex = 0;
00620 } else {
00621
00622 merge(j1, j2);
00623
00624
00625 j2 = j1 = candidates->begin();
00626 j2_relindex = 0;
00627 }
00628 }
00629
00630
00631
00632
00633 j2_relindex++;
00634 if (j2 != candidates->end()) j2++;
00635 }
00636
00637 if (j1 != candidates->end()) {
00638
00639
00640
00641 jets.push_back(*j1);
00642 jets[jets.size()-1].v.build_etaphi();
00643
00644
00645 assert(j1->contents.size() > 0);
00646 jets[jets.size()-1].pass = particles[j1->contents[0]].index;
00647 #ifdef ALLOW_MERGE_IDENTICAL_PROTOCONES
00648 cand_refs.erase(j1->v.ref);
00649 #endif
00650 candidates->erase(j1);
00651
00653
00654
00655
00656
00657 }
00658 }
00659 } while (candidates->size()>0);
00660
00661
00662 sort(jets.begin(), jets.end(), jets_pt_less);
00663 #ifdef DEBUG_SPLIT_MERGE
00664 show();
00665 #endif
00666
00667 return jets.size();
00668 }
00669
00670
00671
00672
00673
00674
00675 int Csplit_merge::save_contents(FILE *flux){
00676 jet_iterator it_j;
00677 Cjet *j1;
00678 int i1, i2;
00679
00680 fprintf(flux, "# %d jets found\n", (int) jets.size());
00681 fprintf(flux, "# columns are: eta, phi, pt and number of particles for each jet\n");
00682 for (it_j = jets.begin(), i1=0 ; it_j != jets.end() ; it_j++, i1++){
00683 j1 = &(*it_j);
00684 j1->v.build_etaphi();
00685 fprintf(flux, "%lf\t%lf\t%le\t%d\n",
00686 j1->v.eta, j1->v.phi, j1->v.perp(), j1->n);
00687 }
00688
00689 fprintf(flux, "# jet contents\n");
00690 fprintf(flux, "# columns are: eta, phi, pt, particle index and jet number\n");
00691 for (it_j = jets.begin(), i1=0 ; it_j != jets.end() ; it_j++, i1++){
00692 j1 = &(*it_j);
00693 for (i2=0;i2<j1->n;i2++)
00694 fprintf(flux, "%lf\t%lf\t%le\t%d\t%d\n",
00695 particles[j1->contents[i2]].eta, particles[j1->contents[i2]].phi,
00696 particles[j1->contents[i2]].perp(), j1->contents[i2], i1);
00697 }
00698
00699 return 0;
00700 }
00701
00702
00703
00704
00705 int Csplit_merge::show(){
00706 jet_iterator it_j;
00707 cjet_iterator it_c;
00708 Cjet *j;
00709 const Cjet *c;
00710 int i1, i2;
00711
00712 for (it_j = jets.begin(), i1=0 ; it_j != jets.end() ; it_j++, i1++){
00713 j = &(*it_j);
00714 fprintf(stdout, "jet %2d: %le\t%le\t%le\t%le\t", i1+1,
00715 j->v.px, j->v.py, j->v.pz, j->v.E);
00716 for (i2=0;i2<j->n;i2++)
00717 fprintf(stdout, "%d ", j->contents[i2]);
00718 fprintf(stdout, "\n");
00719 }
00720
00721 for (it_c = candidates->begin(), i1=0 ; it_c != candidates->end() ; it_c++, i1++){
00722 c = &(*it_c);
00723 fprintf(stdout, "cdt %2d: %le\t%le\t%le\t%le\t%le\t", i1+1,
00724 c->v.px, c->v.py, c->v.pz, c->v.E, sqrt(c->sm_var2));
00725 for (i2=0;i2<c->n;i2++)
00726 fprintf(stdout, "%d ", c->contents[i2]);
00727 fprintf(stdout, "\n");
00728 }
00729
00730 fprintf(stdout, "\n");
00731 return 0;
00732 }
00733
00734
00735
00736
00737
00738
00739
00740
00741 bool Csplit_merge::get_overlap(const Cjet &j1, const Cjet &j2, double *overlap2){
00742
00743 if (!is_range_overlap(j1.range,j2.range))
00744 return false;
00745
00746 int i1,i2;
00747 bool is_overlap;
00748
00749
00750 i1=i2=idx_size=0;
00751 is_overlap = false;
00752 Cmomentum v;
00753 double pt_tilde=0.0;
00754
00755
00756
00757 do{
00758 if (j1.contents[i1]<j2.contents[i2]){
00759 indices[idx_size] = j1.contents[i1];
00760 i1++;
00761 } else if (j1.contents[i1]>j2.contents[i2]){
00762 indices[idx_size] = j2.contents[i2];
00763 i2++;
00764 } else {
00765 v += particles[j1.contents[i1]];
00766 pt_tilde += pt[j1.contents[i1]];
00767 indices[idx_size] = j1.contents[i1];
00768 i1++;
00769 i2++;
00770 is_overlap = true;
00771 }
00772 idx_size++;
00773 } while ((i1<j1.n) && (i2<j2.n));
00774
00775
00776
00777 if (is_overlap){
00778 while (i1<j1.n){
00779 indices[idx_size] = j1.contents[i1];
00780 i1++;
00781 idx_size++;
00782 }
00783 while (i2<j2.n){
00784 indices[idx_size] = j2.contents[i2];
00785 i2++;
00786 idx_size++;
00787 }
00788 }
00789
00790
00791 (*overlap2) = get_sm_var2(v, pt_tilde);
00792
00793 return is_overlap;
00794 }
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00808 bool Csplit_merge::split(cjet_iterator &it_j1, cjet_iterator &it_j2){
00809 int i1, i2;
00810 Cjet jet1, jet2;
00811 double eta1, phi1, eta2, phi2;
00812 double dx1, dy1, dx2, dy2;
00813 Cmomentum tmp;
00814 Cmomentum *v;
00815
00816
00817 const Cjet & j1 = * it_j1;
00818 const Cjet & j2 = * it_j2;
00819
00820 i1=i2=0;
00821 jet2.v = jet1.v = Cmomentum();
00822 jet2.pt_tilde = jet1.pt_tilde = 0.0;
00823
00824
00825 tmp = j1.v;
00826 tmp.build_etaphi();
00827 eta1 = tmp.eta;
00828 phi1 = tmp.phi;
00829
00830 tmp = j2.v;
00831 tmp.build_etaphi();
00832 eta2 = tmp.eta;
00833 phi2 = tmp.phi;
00834
00835 jet1.v = jet2.v = Cmomentum();
00836
00837
00838 do{
00839 if (j1.contents[i1]<j2.contents[i2]){
00840
00841 v = &(particles[j1.contents[i1]]);
00842 jet1.contents.push_back(j1.contents[i1]);
00843 jet1.v += *v;
00844 jet1.pt_tilde += pt[j1.contents[i1]];
00845 i1++;
00846 jet1.range.add_particle(v->eta,v->phi);
00847 } else if (j1.contents[i1]>j2.contents[i2]){
00848
00849 v = &(particles[j2.contents[i2]]);
00850 jet2.contents.push_back(j2.contents[i2]);
00851 jet2.v += *v;
00852 jet2.pt_tilde += pt[j2.contents[i2]];
00853 i2++;
00854 jet2.range.add_particle(v->eta,v->phi);
00855 } else {
00856
00857 v = &(particles[j1.contents[i1]]);
00858
00859
00860 dx1 = eta1 - v->eta;
00861 dy1 = fabs(phi1 - v->phi);
00862 if (dy1>M_PI)
00863 dy1 -= twopi;
00864
00865
00866 dx2 = eta2 - v->eta;
00867 dy2 = fabs(phi2 - v->phi);
00868 if (dy2>M_PI)
00869 dy2 -= twopi;
00870
00871
00872 double d1sq = dx1*dx1+dy1*dy1;
00873 double d2sq = dx2*dx2+dy2*dy2;
00874
00875 if (fabs(d1sq-d2sq) < most_ambiguous_split)
00876 most_ambiguous_split = fabs(d1sq-d2sq);
00877
00878 if (d1sq<d2sq){
00879
00880 jet1.contents.push_back(j1.contents[i1]);
00881 jet1.v += *v;
00882 jet1.pt_tilde += pt[j1.contents[i1]];
00883 jet1.range.add_particle(v->eta,v->phi);
00884 } else {
00885
00886 jet2.contents.push_back(j2.contents[i2]);
00887 jet2.v += *v;
00888 jet2.pt_tilde += pt[j2.contents[i2]];
00889 jet2.range.add_particle(v->eta,v->phi);
00890 }
00891
00892 i1++;
00893 i2++;
00894 }
00895 } while ((i1<j1.n) && (i2<j2.n));
00896
00897 while (i1<j1.n){
00898 v = &(particles[j1.contents[i1]]);
00899 jet1.contents.push_back(j1.contents[i1]);
00900 jet1.v += *v;
00901 jet1.pt_tilde += pt[j1.contents[i1]];
00902 i1++;
00903 jet1.range.add_particle(v->eta,v->phi);
00904 }
00905 while (i2<j2.n){
00906 v = &(particles[j2.contents[i2]]);
00907 jet2.contents.push_back(j2.contents[i2]);
00908 jet2.v += *v;
00909 jet2.pt_tilde += pt[j2.contents[i2]];
00910 i2++;
00911 jet2.range.add_particle(v->eta,v->phi);
00912 }
00913
00914
00915 jet1.n = jet1.contents.size();
00916 jet2.n = jet2.contents.size();
00917
00918
00919
00920
00921
00922 #ifdef ALLOW_MERGE_IDENTICAL_PROTOCONES
00923 cand_refs.erase(j1.v.ref);
00924 cand_refs.erase(j2.v.ref);
00925 #endif
00926 candidates->erase(it_j1);
00927 candidates->erase(it_j2);
00928
00929
00930 insert(jet1);
00931 insert(jet2);
00932
00933 return true;
00934 }
00935
00936
00937
00938
00939
00940
00941
00943 bool Csplit_merge::merge(cjet_iterator &it_j1, cjet_iterator &it_j2){
00944 Cjet jet;
00945 int i;
00946
00947
00948
00949 for (i=0;i<idx_size;i++){
00950 jet.contents.push_back(indices[i]);
00951 jet.v += particles[indices[i]];
00952 jet.pt_tilde += pt[indices[i]];
00953 }
00954 jet.n = jet.contents.size();
00955
00956
00957 jet.range = range_union(it_j1->range, it_j2->range);
00958
00959
00960 #ifdef ALLOW_MERGE_IDENTICAL_PROTOCONES
00961 if (merge_identical_protocones){
00962 cand_refs.erase(it_j1->v.ref);
00963 cand_refs.erase(it_j2->v.ref);
00964 }
00965 #endif
00966 candidates->erase(it_j1);
00967 candidates->erase(it_j2);
00968
00969
00970 insert(jet);
00971
00972 return true;
00973 }
00974
00980 bool Csplit_merge::insert(Cjet &jet){
00981
00982
00983
00984
00985 #ifdef ALLOW_MERGE_IDENTICAL_PROTOCONES
00986 if ((merge_identical_protocones) && (!cand_refs.insert(jet.v.ref).second))
00987 return false;
00988 #endif
00989
00990
00991 if (jet.v.perp2()<pt_min2)
00992 return false;
00993
00994
00995 jet.sm_var2 = get_sm_var2(jet.v, jet.pt_tilde);
00996
00997
00998 candidates->insert(jet);
00999
01000 return true;
01001 }
01002
01009 double Csplit_merge::get_sm_var2(Cmomentum &v, double &pt_tilde){
01010 switch(ptcomparison.split_merge_scale) {
01011 case SM_pt: return v.perp2();
01012 case SM_mt: return v.perpmass2();
01013 case SM_pttilde: return pt_tilde*pt_tilde;
01014 case SM_Et: return v.Et2();
01015 default:
01016 throw Csiscone_error("Unsupported split-merge scale choice: "
01017 + ptcomparison.SM_scale_name());
01018 }
01019
01020 return 0.0;
01021 }
01022
01023 }