00001
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00054 #ifndef __SISCONE_PARTON_H__
00055 #define __SISCONE_PARTON_H__
00056
00057 namespace siscone_jet_algorithm {
00058
00059 const double Pi = 3.14159265358979;
00060
00069 template<class T> class siscone_parton
00070 {
00071
00072 public:
00073 siscone_parton(int n_particles_max);
00074
00075
00076 public:
00077 int compute_jets(const std::vector<T> & particles, double R, double f, int n_pass_max=0, double ptmin=0.0);
00078
00079 void set_flag_total_pt_is_zero(bool flag);
00080
00081
00082 public:
00084 std::vector<unsigned> final_jets;
00085
00087 std::vector<unsigned> protojets;
00088
00090 std::vector<T> protojets_axis;
00091
00093 std::vector<double> protojets_pt;
00094
00096 std::vector<double> protojets_pttilde;
00097
00099 std::vector<double> protojets_azimuthal_angle;
00100
00102 std::vector<double> protojets_rapidity;
00103
00105 std::vector<bool> flag_rapidity;
00106
00108 bool flag_total_pt_is_zero;
00109 };
00110
00118 template<class T> siscone_parton<T>::siscone_parton(int n) :
00119 final_jets(), protojets(), protojets_axis(1<<n,T()), protojets_pt(1<<n,double(0.0)), protojets_pttilde(1<<n,double(0.0)),
00120 protojets_azimuthal_angle(1<<n,double(0.0)), protojets_rapidity(1<<n,double(0.0)), flag_rapidity(1<<n,bool(false)),
00121 flag_total_pt_is_zero(false)
00122 {
00123 final_jets.reserve(n);
00124
00125 protojets.reserve(1<<n);
00126 }
00127
00133 template<class T> void siscone_parton<T>::set_flag_total_pt_is_zero(bool flag)
00134 {
00135 flag_total_pt_is_zero = flag;
00136 }
00137
00149 template<class T> int siscone_parton<T>::compute_jets(const std::vector<T> & p, double R, double f, int n_pass_max, double ptmin)
00150 {
00151
00152 double CUT_Y = R*R;
00153
00154
00155 bool flag_new_stable_cone_found;
00156
00157 int n = p.size();
00158
00159
00160
00161 unsigned mask_all = (1<<n) - 1;
00162 unsigned current_set = mask_all;
00163 unsigned mask_remove = 0;
00164
00165 int i_pass = 0;
00166
00167
00168 final_jets.clear();
00169 protojets.clear();
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188 for (unsigned i=0; i<n; i++)
00189 {
00190 for (unsigned j=0; j<(1<<i); j++)
00191 {
00192 unsigned index = (1<<i) + j;
00193 protojets_axis[index] = p[i];
00194 if (j) protojets_axis[index].sum_up(protojets_axis[j]);
00195
00196 protojets_pt[index] = protojets_axis[index].transverse_momentum();
00197
00198 protojets_pttilde[index] = protojets_pt[1<<i];
00199 if (j) protojets_pttilde[index] += protojets_pttilde[j];
00200
00201 flag_rapidity[index] = false;
00202 }
00203 }
00204
00205
00206 if ( flag_total_pt_is_zero )
00207 {
00208 for (unsigned index=0; index<(1<<(n-1)); index++)
00209 {
00210 protojets_azimuthal_angle[index] = protojets_axis[index].azimuthal_angle();
00211 protojets_azimuthal_angle[index^mask_all] = Pi + protojets_azimuthal_angle[index];
00212 if ( protojets_azimuthal_angle[index^mask_all] > Pi ) protojets_azimuthal_angle[index^mask_all] -= 2.0*Pi;
00213 }
00214 }
00215 else
00216 {
00217 for (unsigned index=0; index<(1<<n); index++) protojets_azimuthal_angle[index] = protojets_axis[index].azimuthal_angle();
00218 }
00219
00220
00221 for (unsigned i=0; i<n; i++)
00222 {
00223 protojets_rapidity[1<<i] = protojets_axis[1<<i].rapidity();
00224 flag_rapidity[1<<i] = true;
00225 }
00226
00227
00228
00229 do
00230 {
00231 flag_new_stable_cone_found = false;
00232
00233
00234 current_set ^= mask_remove;
00235 mask_remove = 0;
00236
00237
00238
00239
00240 for (unsigned i_possibilities=1; i_possibilities<=mask_all; i_possibilities++)
00241 {
00242
00243 if ( !(i_possibilities & ~current_set) )
00244 {
00245 bool flag_stable_cone=true;
00246
00247
00248
00249
00250
00251 for (size_t i=0; i<n; i++)
00252 {
00253
00254 if ( flag_stable_cone && (current_set & (1<<i)) )
00255 {
00256 double delta_phi_angle = fabs( protojets_azimuthal_angle[1<<i] - protojets_azimuthal_angle[i_possibilities] );
00257 if (delta_phi_angle > Pi) delta_phi_angle = 2*Pi-delta_phi_angle;
00258
00259 double y_R_i = delta_phi_angle*delta_phi_angle;
00260
00261 if ( i_possibilities & (1<<i) )
00262 {
00263
00264 if ( y_R_i>CUT_Y ) flag_stable_cone=false;
00265 }
00266 }
00267 }
00268
00269
00270
00271 if ( flag_stable_cone )
00272 {
00273 if ( !flag_rapidity[i_possibilities] )
00274 {
00275 protojets_rapidity[i_possibilities] = protojets_axis[i_possibilities].rapidity();
00276 flag_rapidity[i_possibilities] = true;
00277 }
00278
00279 for (size_t i=0; i<n; i++)
00280 {
00281
00282 if ( flag_stable_cone && (current_set & (1<<i)) )
00283 {
00284 double delta_rapidity = protojets_rapidity[1<<i] - protojets_rapidity[i_possibilities];
00285 double delta_phi_angle = fabs( protojets_azimuthal_angle[1<<i] - protojets_azimuthal_angle[i_possibilities] );
00286 if (delta_phi_angle > Pi) delta_phi_angle = 2*Pi-delta_phi_angle;
00287
00288 double y_R_i = delta_rapidity*delta_rapidity + delta_phi_angle*delta_phi_angle;
00289
00290 if ( i_possibilities & (1<<i) )
00291 {
00292
00293 if ( y_R_i>CUT_Y ) flag_stable_cone=false;
00294 }
00295 else
00296 {
00297
00298 if ( y_R_i<=CUT_Y ) flag_stable_cone=false;
00299 }
00300 }
00301 }
00302 }
00303
00304
00305 if (flag_stable_cone)
00306 {
00307 flag_new_stable_cone_found=true;
00308
00309
00310 protojets.push_back(i_possibilities);
00311
00312
00313 mask_remove |= i_possibilities;
00314 }
00315 }
00316 }
00317
00318 i_pass++;
00319 }
00320 while (flag_new_stable_cone_found && (( i_pass < n_pass_max ) || ( n_pass_max == 0 )) );
00321
00322
00323
00324
00325
00326 while ( protojets.size() )
00327 {
00328
00329 for (int i=protojets.size()-1; i>=0; i--)
00330 {
00331 if ( protojets_pt[protojets[i]] < ptmin ) protojets.erase(protojets.begin()+i);
00332 }
00333
00334
00335 if ( protojets.size() )
00336 {
00337 size_t i_max = 0;
00338 double pttilde_max = protojets_pttilde[protojets[0]];
00339
00340 for (size_t i=1; i<protojets.size(); i++)
00341 {
00342 if ( protojets_pttilde[protojets[i]] > pttilde_max )
00343 {
00344 i_max = i;
00345 pttilde_max = protojets_pttilde[protojets[i]];
00346 }
00347 }
00348
00349
00350 bool flag_overlap = false;
00351 size_t i_overlap;
00352 double pttilde_overlap;
00353 for (size_t i=0; i<protojets.size(); i++)
00354 {
00355 if ( ( i != i_max ) && (protojets[i] & protojets[i_max]) )
00356 {
00357 if ( flag_overlap )
00358 {
00359
00360 if ( protojets_pttilde[protojets[i]] > pttilde_overlap )
00361 {
00362 i_overlap = i;
00363 pttilde_overlap = protojets_pttilde[protojets[i]];
00364 }
00365 }
00366 else
00367 {
00368
00369 i_overlap = i;
00370 pttilde_overlap = protojets_pttilde[protojets[i]];
00371
00372 flag_overlap = true;
00373 }
00374 }
00375 }
00376
00377 if ( flag_overlap )
00378 {
00379 unsigned index_i_max = protojets[i_max];
00380 unsigned index_i_overlap = protojets[i_overlap];
00381
00382 unsigned mask_shared = index_i_max & index_i_overlap;
00383
00384
00385 double ptoverlap = protojets_pttilde[index_i_overlap];
00386 double ptshared = protojets_pttilde[mask_shared];
00387
00388 if ( ptshared < f*ptoverlap )
00389 {
00390
00391 unsigned assign_to_i_max = 0;
00392 unsigned assign_to_i_overlap = 0;
00393
00394
00395 if ( !flag_rapidity[index_i_max] )
00396 {
00397 protojets_rapidity[index_i_max] = protojets_axis[index_i_max].rapidity();
00398 flag_rapidity[index_i_max] = true;
00399 }
00400
00401 if ( !flag_rapidity[index_i_overlap] )
00402 {
00403 protojets_rapidity[index_i_overlap] = protojets_axis[index_i_overlap].rapidity();
00404 flag_rapidity[index_i_overlap] = true;
00405 }
00406
00407 for (int i=0; i<n; i++)
00408 {
00409 unsigned mask_shifted = (1<<i);
00410
00411 if ( mask_shared & mask_shifted )
00412 {
00413 double delta_rapidity_i_imax = protojets_rapidity[1<<i] - protojets_rapidity[index_i_max];
00414 double delta_phi_angle_i_imax = fabs( protojets_azimuthal_angle[1<<i] - protojets_azimuthal_angle[index_i_max] );
00415 if (delta_phi_angle_i_imax > Pi) delta_phi_angle_i_imax = 2*Pi-delta_phi_angle_i_imax;
00416
00417
00418 double delta_rapidity_i_ioverlap = protojets_rapidity[1<<i] - protojets_rapidity[index_i_overlap];
00419 double delta_phi_angle_i_ioverlap = fabs( protojets_azimuthal_angle[1<<i] - protojets_azimuthal_angle[index_i_overlap] );
00420 if (delta_phi_angle_i_ioverlap > Pi) delta_phi_angle_i_ioverlap = 2*Pi-delta_phi_angle_i_ioverlap;
00421
00422 double y_i_imax = delta_rapidity_i_imax*delta_rapidity_i_imax + delta_phi_angle_i_imax*delta_phi_angle_i_imax;
00423 double y_i_ioverlap = delta_rapidity_i_ioverlap*delta_rapidity_i_ioverlap + delta_phi_angle_i_ioverlap*delta_phi_angle_i_ioverlap;
00424
00425 if ( y_i_imax < y_i_ioverlap )
00426 {
00427
00428 assign_to_i_max |= mask_shifted;
00429 }
00430 else
00431 {
00432
00433 assign_to_i_overlap |= mask_shifted;
00434 }
00435 }
00436 }
00437
00438
00439 if ( assign_to_i_max ) protojets[i_overlap] ^= assign_to_i_max;
00440
00441
00442 if ( assign_to_i_overlap ) protojets[i_max] ^= assign_to_i_overlap;
00443
00444 }
00445 else
00446 {
00447
00448 protojets[i_max] |= index_i_overlap;
00449 protojets.erase(protojets.begin()+i_overlap);
00450 }
00451 }
00452 else
00453 {
00454 final_jets.push_back( protojets[i_max] );
00455
00456 protojets.erase(protojets.begin()+i_max);
00457 }
00458
00459 }
00460 }
00461
00462 return final_jets.size();
00463 }
00464
00473 template<class T> class siscone_spherical_parton
00474 {
00475
00476 public:
00477 siscone_spherical_parton(int n_particles_max);
00478
00479
00480 public:
00481 int compute_jets(const std::vector<T> & particles, double R, double f, int n_pass_max=0, double Emin=0.0);
00482
00483
00484 public:
00486 std::vector<unsigned> final_jets;
00487
00489 std::vector<unsigned> protojets;
00490
00492 std::vector<T> protojets_axis;
00493
00495 std::vector<double> protojets_E;
00496
00498 std::vector<double> protojets_Etilde;
00499
00501 std::vector<double> protojets_f;
00502 };
00503
00511 template<class T> siscone_spherical_parton<T>::siscone_spherical_parton(int n) :
00512 final_jets(), protojets(), protojets_axis(1<<n,T()), protojets_E(1<<n,double(0.0)), protojets_Etilde(1<<n,double(0.0)), protojets_f(1<<n,double(0.0))
00513 {
00514 final_jets.reserve(n);
00515
00516 protojets.reserve(1<<n);
00517 }
00518
00530 template<class T> int siscone_spherical_parton<T>::compute_jets(const std::vector<T> & p, double R, double f, int n_pass_max, double Emin)
00531 {
00532
00533
00534 double CUT_Y = 1.0-cos(R);
00535
00536
00537 bool flag_new_stable_cone_found;
00538
00539 int n = p.size();
00540
00541
00542
00543 unsigned mask_all = (1<<n) - 1;
00544 unsigned current_set = mask_all;
00545 unsigned mask_remove = 0;
00546
00547 int i_pass = 0;
00548
00549
00550 final_jets.clear();
00551 protojets.clear();
00552
00553
00554 for (unsigned i=0; i<n; i++)
00555 {
00556 for (unsigned j=0; j<(1<<i); j++)
00557 {
00558 unsigned index = (1<<i) + j;
00559 protojets_axis[index] = p[i];
00560 if (j) protojets_axis[index].sum_up(protojets_axis[j]);
00561 }
00562 }
00563 for (unsigned i=1; i<mask_all+1; i++)
00564 {
00565 protojets_E[i] = protojets_axis[i].energy_component();
00566 protojets_f[i] = sqrt( protojets_axis[i].spatial_norm() );
00567 }
00568 for (unsigned i=1; i<mask_all; i++) protojets_axis[i].rescale( 1.0/protojets_f[i] );
00569
00570 for (unsigned i=1; i<mask_all+1; i++)
00571 {
00572 double fudge = protojets_f[i]/protojets_E[i];
00573 protojets_f[i] = fudge*fudge;
00574 }
00575
00576
00577
00578 do
00579 {
00580 flag_new_stable_cone_found = false;
00581
00582
00583 current_set ^= mask_remove;
00584 mask_remove = 0;
00585
00586
00587
00588 for (unsigned i_possibilities=1; i_possibilities<mask_all; i_possibilities++)
00589 {
00590
00591 if ( !(i_possibilities & ~current_set) )
00592 {
00593
00594 bool flag_stable_cone=true;
00595 double Etilde = 0.0;
00596 for (size_t i=0; i<n; i++)
00597 {
00598
00599 if ( flag_stable_cone && (current_set & (1<<i)) )
00600 {
00601 double y_R_i = 1.0 - protojets_axis[1<<i].spatial_scalar_product(protojets_axis[i_possibilities]);
00602
00603 if ( i_possibilities & (1<<i) )
00604 {
00605 if ( y_R_i<=CUT_Y )
00606 {
00607
00608 Etilde += p[i].energy_component() * (1.0+protojets_f[i_possibilities]*y_R_i*(2.0-y_R_i));
00609 }
00610 else
00611 {
00612
00613 flag_stable_cone=false;
00614 }
00615 }
00616 else
00617 {
00618
00619 if ( y_R_i<=CUT_Y ) flag_stable_cone=false;
00620 }
00621 }
00622 }
00623
00624
00625 if (flag_stable_cone)
00626 {
00627 flag_new_stable_cone_found=true;
00628
00629
00630 protojets.push_back(i_possibilities);
00631 protojets_Etilde[i_possibilities] = Etilde;
00632
00633
00634 mask_remove |= i_possibilities;
00635 }
00636 }
00637 }
00638
00639 i_pass++;
00640 }
00641 while (flag_new_stable_cone_found && (( i_pass < n_pass_max ) || ( n_pass_max == 0 )) );
00642
00643
00644
00645
00646
00647 while ( protojets.size() )
00648 {
00649
00650 for (int i=protojets.size()-1; i>=0; i--)
00651 {
00652 if ( protojets_E[protojets[i]] < Emin ) protojets.erase(protojets.begin()+i);
00653 }
00654
00655
00656 if ( protojets.size() )
00657 {
00658 size_t i_max = 0;
00659 double Etilde_max = protojets_Etilde[protojets[0]];
00660
00661 for (size_t i=1; i<protojets.size(); i++)
00662 {
00663 if ( protojets_Etilde[protojets[i]] > Etilde_max )
00664 {
00665 i_max = i;
00666 Etilde_max = protojets_Etilde[protojets[i]];
00667 }
00668 }
00669
00670
00671 bool flag_overlap = false;
00672 size_t i_overlap;
00673 double Etilde_overlap;
00674 for (size_t i=0; i<protojets.size(); i++)
00675 {
00676 if ( ( i != i_max ) && (protojets[i] & protojets[i_max]) )
00677 {
00678 if ( flag_overlap )
00679 {
00680
00681 if ( protojets_Etilde[protojets[i]] > Etilde_overlap )
00682 {
00683 i_overlap = i;
00684 Etilde_overlap = protojets_Etilde[protojets[i]];
00685 }
00686 }
00687 else
00688 {
00689
00690 i_overlap = i;
00691 Etilde_overlap = protojets_Etilde[protojets[i]];
00692
00693 flag_overlap = true;
00694 }
00695 }
00696 }
00697
00698 if ( flag_overlap )
00699 {
00700 unsigned mask_shared = protojets[i_max] & protojets[i_overlap];
00701
00702
00703 double Eoverlap = protojets_E[protojets[i_overlap]];
00704 double Eshared = protojets_E[mask_shared];
00705
00706 if ( Eshared < f*Eoverlap )
00707 {
00708
00709 unsigned assign_to_i_max = 0;
00710 unsigned assign_to_i_overlap = 0;
00711
00712 for (int i=0; i<n; i++)
00713 {
00714 unsigned mask_shifted = (1<<i);
00715
00716 if ( mask_shared & mask_shifted )
00717 {
00718 double y_i_imax = 1.0 - protojets_axis[1<<i].spatial_scalar_product(protojets_axis[protojets[i_max]]);
00719 double y_i_ioverlap = 1.0 - protojets_axis[1<<i].spatial_scalar_product(protojets_axis[protojets[i_overlap]]);
00720
00721 if ( y_i_imax < y_i_ioverlap )
00722 {
00723
00724 assign_to_i_max |= mask_shifted;
00725 }
00726 else
00727 {
00728
00729 assign_to_i_overlap |= mask_shifted;
00730 }
00731 }
00732 }
00733
00734
00735 if ( assign_to_i_max )
00736 {
00737 protojets[i_overlap] ^= assign_to_i_max;
00738
00739
00740 double Etilde = 0.0;
00741 for (int i=0; i<n; i++)
00742 {
00743 if ( protojets[i_overlap] & (1<<i) )
00744 {
00745 double y_R_i = 1.0 - protojets_axis[1<<i].spatial_scalar_product(protojets_axis[protojets[i_overlap]]);
00746 Etilde += p[i].energy_component() *(1.0+protojets_f[protojets[i_overlap]]*y_R_i*(2.0-y_R_i));
00747 }
00748 }
00749 protojets_Etilde[protojets[i_overlap]] = Etilde;
00750 }
00751
00752
00753 if ( assign_to_i_overlap )
00754 {
00755 protojets[i_max] ^= assign_to_i_overlap;
00756
00757
00758 double Etilde = 0.0;
00759 for (int i=0; i<n; i++)
00760 {
00761 if ( protojets[i_max] & (1<<i) )
00762 {
00763 double y_R_i = 1.0 - protojets_axis[1<<i].spatial_scalar_product(protojets_axis[protojets[i_max]]);
00764 Etilde += p[i].energy_component() *(1.0+protojets_f[protojets[i_max]]*y_R_i*(2.0-y_R_i));
00765 }
00766 }
00767 protojets_Etilde[protojets[i_max]] = Etilde;
00768 }
00769
00770 }
00771 else
00772 {
00773
00774 unsigned mask_union = protojets[i_max] | protojets[i_overlap];
00775
00776
00777 double Etilde = 0.0;
00778 for (int i=0; i<n; i++)
00779 {
00780 if ( mask_union & (1<<i) )
00781 {
00782 double y_R_i = 1.0 - protojets_axis[1<<i].spatial_scalar_product(protojets_axis[mask_union]);
00783 Etilde += p[i].energy_component() *(1.0+protojets_f[mask_union]*y_R_i*(2.0-y_R_i));
00784 }
00785 }
00786 protojets_Etilde[mask_union] = Etilde;
00787
00788
00789 protojets[i_max] = mask_union;
00790 protojets.erase(protojets.begin()+i_overlap);
00791 }
00792 }
00793 else
00794 {
00795 final_jets.push_back( protojets[i_max] );
00796
00797 protojets.erase(protojets.begin()+i_max);
00798 }
00799
00800 }
00801 }
00802
00803 return final_jets.size();
00804 }
00805
00806 }
00807
00808 #endif // ndef __SISCONE_PARTON_H__
00809