70.1.5
by Benjamin Fuks
MT2 variable + macos change of stdc++ library (bug #1250337) + ... |
1 |
////////////////////////////////////////////////////////////////////////////////
|
112.1.50
by Eric Conte
update all-file with MA5banner + logging.getLogger(MA5) |
2 |
//
|
3 |
// Copyright (C) 2012-2016 Eric Conte, Benjamin Fuks
|
|
70.1.5
by Benjamin Fuks
MT2 variable + macos change of stdc++ library (bug #1250337) + ... |
4 |
// The MadAnalysis development team, email: <ma5team@iphc.cnrs.fr>
|
112.1.50
by Eric Conte
update all-file with MA5banner + logging.getLogger(MA5) |
5 |
//
|
70.1.5
by Benjamin Fuks
MT2 variable + macos change of stdc++ library (bug #1250337) + ... |
6 |
// This file is part of MadAnalysis 5.
|
7 |
// Official website: <https://launchpad.net/madanalysis5>
|
|
112.1.50
by Eric Conte
update all-file with MA5banner + logging.getLogger(MA5) |
8 |
//
|
70.1.5
by Benjamin Fuks
MT2 variable + macos change of stdc++ library (bug #1250337) + ... |
9 |
// MadAnalysis 5 is free software: you can redistribute it and/or modify
|
10 |
// it under the terms of the GNU General Public License as published by
|
|
11 |
// the Free Software Foundation, either version 3 of the License, or
|
|
12 |
// (at your option) any later version.
|
|
112.1.50
by Eric Conte
update all-file with MA5banner + logging.getLogger(MA5) |
13 |
//
|
70.1.5
by Benjamin Fuks
MT2 variable + macos change of stdc++ library (bug #1250337) + ... |
14 |
// MadAnalysis 5 is distributed in the hope that it will be useful,
|
15 |
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
16 |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
17 |
// GNU General Public License for more details.
|
|
112.1.50
by Eric Conte
update all-file with MA5banner + logging.getLogger(MA5) |
18 |
//
|
70.1.5
by Benjamin Fuks
MT2 variable + macos change of stdc++ library (bug #1250337) + ... |
19 |
// You should have received a copy of the GNU General Public License
|
20 |
// along with MadAnalysis 5. If not, see <http://www.gnu.org/licenses/>
|
|
112.1.50
by Eric Conte
update all-file with MA5banner + logging.getLogger(MA5) |
21 |
//
|
70.1.5
by Benjamin Fuks
MT2 variable + macos change of stdc++ library (bug #1250337) + ... |
22 |
////////////////////////////////////////////////////////////////////////////////
|
23 |
||
112.1.50
by Eric Conte
update all-file with MA5banner + logging.getLogger(MA5) |
24 |
|
70.1.5
by Benjamin Fuks
MT2 variable + macos change of stdc++ library (bug #1250337) + ... |
25 |
// STL headers
|
115.1.9
by Eric Conte
replace fabs by std::abs |
26 |
#include <cmath> |
27 |
||
70.1.5
by Benjamin Fuks
MT2 variable + macos change of stdc++ library (bug #1250337) + ... |
28 |
// SampleAnalyzer headers
|
72.1.29
by Eric Conte
new compilation structure |
29 |
#include "SampleAnalyzer/Commons/Service/TransverseVariables.h" |
30 |
#include "SampleAnalyzer/Commons/Service/LogService.h" |
|
31 |
#include "SampleAnalyzer/Commons/Service/SortingService.h" |
|
109.1.45
by Eric Conte
no more Root first step |
32 |
#include "SampleAnalyzer/Commons/Vector/MARotation3axis.h" |
33 |
||
70.1.5
by Benjamin Fuks
MT2 variable + macos change of stdc++ library (bug #1250337) + ... |
34 |
|
35 |
using namespace MA5; |
|
36 |
||
70.1.34
by Benjamin Fuks
Implementation of the MT2W variable + sorting functions |
37 |
/// -----------------------------------------------
|
38 |
/// Funcions related to the computation of the mt2
|
|
39 |
/// -----------------------------------------------
|
|
70.1.5
by Benjamin Fuks
MT2 variable + macos change of stdc++ library (bug #1250337) + ... |
40 |
|
41 |
inline int signchange_n(long double t1,long double t2,long double t3,long double t4,long double t5) |
|
42 |
{
|
|
43 |
int nsc=0; |
|
44 |
if(t1*t2>0) nsc++; |
|
45 |
if(t2*t3>0) nsc++; |
|
46 |
if(t3*t4>0) nsc++; |
|
47 |
if(t4*t5>0) nsc++; |
|
48 |
return nsc; |
|
49 |
}
|
|
50 |
||
51 |
inline int signchange_p(long double t1,long double t2,long double t3,long double t4,long double t5) |
|
52 |
{
|
|
53 |
int nsc=0; |
|
54 |
if(t1*t2<0) nsc++; |
|
55 |
if(t2*t3<0) nsc++; |
|
56 |
if(t3*t4<0) nsc++; |
|
57 |
if(t4*t5<0) nsc++; |
|
58 |
return nsc; |
|
59 |
}
|
|
60 |
||
70.1.34
by Benjamin Fuks
Implementation of the MT2W variable + sorting functions |
61 |
int TransverseVariables::Nsolutions(const double &E) |
70.1.5
by Benjamin Fuks
MT2 variable + macos change of stdc++ library (bug #1250337) + ... |
62 |
{
|
63 |
//obtain the coefficients for the 4th order equation
|
|
64 |
//divided by Ea^n to make the variable dimensionless
|
|
65 |
long double A4 = -4.*C2_[0]*C1_[1]*C2_[1]*C1_[2] + 4.*C1_[0]*C2_[1]*C2_[1]*C1_[2] + |
|
66 |
C2_[0]*C2_[0]*C1_[2]*C1_[2] + 4.*C2_[0]*C1_[1]*C1_[1]*C2_[2] - |
|
67 |
4.*C1_[0]*C1_[1]*C2_[1]*C2_[2] - 2.*C1_[0]*C2_[0]*C1_[2]*C2_[2] + C1_[0]*C1_[0]*C2_[2]*C2_[2]; |
|
68 |
long double A3 = (-4.*C2_[0]*C2_[1]*C1_[2]*C1_[3] + 8.*C2_[0]*C1_[1]*C2_[2]*C1_[3] - |
|
69 |
4.*C1_[0]*C2_[1]*C2_[2]*C1_[3] - 4.*C2_[0]*C1_[1]*C1_[2]*C2_[3] + |
|
70 |
8.*C1_[0]*C2_[1]*C1_[2]*C2_[3] - 4.*C1_[0]*C1_[1]*C2_[2]*C2_[3] - |
|
71 |
8.*C2_[0]*C1_[1]*C2_[1]*C1_[4] + 8.*C1_[0]*C2_[1]*C2_[1]*C1_[4] + |
|
72 |
4.*C2_[0]*C2_[0]*C1_[2]*C1_[4] - 4.*C1_[0]*C2_[0]*C2_[2]*C1_[4] + |
|
73 |
8.*C2_[0]*C1_[1]*C1_[1]*C2_[4] - 8.*C1_[0]*C1_[1]*C2_[1]*C2_[4] - |
|
70.1.34
by Benjamin Fuks
Implementation of the MT2W variable + sorting functions |
74 |
4.*C1_[0]*C2_[0]*C1_[2]*C2_[4] + 4.*C1_[0]*C1_[0]*C2_[2]*C2_[4])/E; |
70.1.5
by Benjamin Fuks
MT2 variable + macos change of stdc++ library (bug #1250337) + ... |
75 |
long double A2 = (4.*C2_[0]*C2_[2]*C1_[3]*C1_[3] - 4.*C2_[0]*C1_[2]*C1_[3]*C2_[3] - |
76 |
4.*C1_[0]*C2_[2]*C1_[3]*C2_[3] + 4.*C1_[0]*C1_[2]*C2_[3]*C2_[3] - |
|
77 |
8.*C2_[0]*C2_[1]*C1_[3]*C1_[4] - 8.*C2_[0]*C1_[1]*C2_[3]*C1_[4] + |
|
78 |
16.*C1_[0]*C2_[1]*C2_[3]*C1_[4] + 4.*C2_[0]*C2_[0]*C1_[4]*C1_[4] + |
|
79 |
16.*C2_[0]*C1_[1]*C1_[3]*C2_[4] - 8.*C1_[0]*C2_[1]*C1_[3]*C2_[4] - |
|
80 |
8.*C1_[0]*C1_[1]*C2_[3]*C2_[4] - 8.*C1_[0]*C2_[0]*C1_[4]*C2_[4] + |
|
81 |
4.*C1_[0]*C1_[0]*C2_[4]*C2_[4] - 4.*C2_[0]*C1_[1]*C2_[1]*C1_[5] + |
|
82 |
4.*C1_[0]*C2_[1]*C2_[1]*C1_[5] + 2.*C2_[0]*C2_[0]*C1_[2]*C1_[5] - |
|
83 |
2.*C1_[0]*C2_[0]*C2_[2]*C1_[5] + 4.*C2_[0]*C1_[1]*C1_[1]*C2_[5] - |
|
84 |
4.*C1_[0]*C1_[1]*C2_[1]*C2_[5] - 2.*C1_[0]*C2_[0]*C1_[2]*C2_[5] + |
|
70.1.34
by Benjamin Fuks
Implementation of the MT2W variable + sorting functions |
85 |
2.*C1_[0]*C1_[0]*C2_[2]*C2_[5])/pow(E,2.); |
70.1.5
by Benjamin Fuks
MT2 variable + macos change of stdc++ library (bug #1250337) + ... |
86 |
long double A1 = (-8.*C2_[0]*C1_[3]*C2_[3]*C1_[4] + 8.*C1_[0]*C2_[3]*C2_[3]*C1_[4] + |
87 |
8.*C2_[0]*C1_[3]*C1_[3]*C2_[4] - 8.*C1_[0]*C1_[3]*C2_[3]*C2_[4] - |
|
88 |
4.*C2_[0]*C2_[1]*C1_[3]*C1_[5] - 4.*C2_[0]*C1_[1]*C2_[3]*C1_[5] + |
|
89 |
8.*C1_[0]*C2_[1]*C2_[3]*C1_[5] + 4.*C2_[0]*C2_[0]*C1_[4]*C1_[5] - |
|
90 |
4.*C1_[0]*C2_[0]*C2_[4]*C1_[5] + 8.*C2_[0]*C1_[1]*C1_[3]*C2_[5] - |
|
91 |
4.*C1_[0]*C2_[1]*C1_[3]*C2_[5] - 4.*C1_[0]*C1_[1]*C2_[3]*C2_[5] - |
|
70.1.34
by Benjamin Fuks
Implementation of the MT2W variable + sorting functions |
92 |
4.*C1_[0]*C2_[0]*C1_[4]*C2_[5] + 4.*C1_[0]*C1_[0]*C2_[4]*C2_[5])/pow(E,3); |
70.1.5
by Benjamin Fuks
MT2 variable + macos change of stdc++ library (bug #1250337) + ... |
93 |
long double A0 = (-4.*C2_[0]*C1_[3]*C2_[3]*C1_[5] + 4.*C1_[0]*C2_[3]*C2_[3]*C1_[5] + |
94 |
C2_[0]*C2_[0]*C1_[5]*C1_[5] + 4.*C2_[0]*C1_[3]*C1_[3]*C2_[5] - |
|
95 |
4.*C1_[0]*C1_[3]*C2_[3]*C2_[5] - 2.*C1_[0]*C2_[0]*C1_[5]*C2_[5] + |
|
70.1.34
by Benjamin Fuks
Implementation of the MT2W variable + sorting functions |
96 |
C1_[0]*C1_[0]*C2_[5]*C2_[5])/pow(E,4); |
70.1.5
by Benjamin Fuks
MT2 variable + macos change of stdc++ library (bug #1250337) + ... |
97 |
|
98 |
long double C2 = -(A2/2. - 3.*pow(A3,2)/(16.*A4)); |
|
99 |
long double C1 = -(3.*A1/4. -A2*A3/(8.*A4)); |
|
100 |
long double C0 = -A0 + A1*A3/(16.*A4); |
|
101 |
long double D1 = -2.*A2 - (4.*A4*C1*C1/C2 - 4.*A4*C0 -3.*A3*C1)/C2; |
|
102 |
long double D0 = -A1 - 4.*A4*C0*C1/pow(C2,2) + 3.*A3*C0/C2; |
|
103 |
long double E0 = -C0 - C2*D0*D0/(D1*D1) + C1*D0/D1; |
|
104 |
||
105 |
// Find the coefficients for the leading term in the Sturm sequence
|
|
106 |
// The number of solutions depends on diffence of number of sign changes
|
|
107 |
// for x->Inf and x->-Inf
|
|
108 |
int nsol = signchange_n(A4,A4,C2,D1,E0) - signchange_p(A4,A4,C2,D1,E0); |
|
109 |
if (nsol < 0) nsol = 0; //rounding effects |
|
110 |
return nsol; |
|
111 |
}
|
|
112 |
||
113 |
||
114 |
template <typename T> int sgn(T val) { return (T(0) < val) - (val < T(0)); } |
|
115 |
||
116 |
int TransverseVariables::Nsolutions_massless(const double &dsq) |
|
117 |
{
|
|
118 |
//obtain the coefficients for the 4th order equation
|
|
119 |
//divided by Ea^n to make the variable dimensionless
|
|
120 |
long double a = sgn(p2_.Px())*p2_.Mt()/dsq; |
|
121 |
long double b = sgn(p2_.Px())*(msq_*p2_.Mt()/dsq - dsq/(4.*p2_.Mt())); |
|
122 |
long double A4 = a*a*C2_[0]; |
|
123 |
long double A3 = 2.*a*C2_[1]/p2_.Mt(); |
|
124 |
long double A2 = (2.*a*C2_[0]*b+C2_[2]+2.*a*C2_[3])/p2_.Mt2(); |
|
125 |
long double A1 = (2.*b*C2_[1]+2.*C2_[4])/pow(p2_.Mt(),3); |
|
126 |
long double A0 = (C2_[0]*b*b+2.*b*C2_[3]+C2_[5])/pow(p2_.Mt2(),2); |
|
127 |
||
128 |
long double C2 = -(A2/2.-3.*pow(A3,2)/(16.*A4)); |
|
129 |
long double C1 = -(3.*A1/4.-A2*A3/(8.*A4)); |
|
130 |
long double C0 = -A0+A1*A3/(16.*A4); |
|
131 |
long double D1 = -2.*A2-(4.*A4*C1*C1/C2 -4.*A4*C0-3.*A3*C1)/C2; |
|
132 |
long double D0 = -A1-4.*A4*C0*C1/(C2*C2)+3.*A3*C0/C2; |
|
133 |
long double E0 = -C0 - C2*D0*D0/(D1*D1) + C1*D0/D1; |
|
134 |
||
135 |
// Find the coefficients for the leading term in the Sturm sequence
|
|
136 |
// The number of solutions depends on diffence of number of sign changes
|
|
137 |
// for x->Inf and x->-Inf
|
|
138 |
int nsol = signchange_n(A4,A4,C2,D1,E0)-signchange_p(A4,A4,C2,D1,E0); |
|
139 |
if( nsol < 0 ) nsol=0; // possible rounding effects |
|
140 |
return nsol; |
|
141 |
}
|
|
142 |
||
143 |
||
144 |
||
145 |
bool TransverseVariables::FindHigh(double &dsqH) |
|
146 |
{
|
|
147 |
double x0 = (C1_[2]*C1_[3]-C1_[1]*C1_[4])/(C1_[1]*C1_[1]-C1_[0]*C1_[2]); |
|
148 |
double y0 = (C1_[0]*C1_[4]-C1_[1]*C1_[3])/(C1_[1]*C1_[1]-C1_[0]*C1_[2]); |
|
70.1.13
by Benjamin Fuks
Small bug in the MT2 routine (thanks to J. Bernon) |
149 |
double dsqL = p2_.M()*(2.*m_+p2_.M()); |
70.1.5
by Benjamin Fuks
MT2 variable + macos change of stdc++ library (bug #1250337) + ... |
150 |
do
|
151 |
{
|
|
152 |
double dsqM = (dsqH + dsqL)/2.; |
|
153 |
UpdateC1((dsqM-p2_.M2())/(2.*p2_.Mt2())); |
|
154 |
UpdateC2(((dsqM-p1_.M2())/2.+p1met_)/p1_.Mt2()); |
|
70.1.34
by Benjamin Fuks
Implementation of the MT2W variable + sorting functions |
155 |
int nsolM = Nsolutions(p2_.Mt()); |
70.1.5
by Benjamin Fuks
MT2 variable + macos change of stdc++ library (bug #1250337) + ... |
156 |
if (nsolM==2) { dsqH = dsqM; return true; } |
157 |
else if(nsolM==4) { dsqH = dsqM; continue; } |
|
158 |
else if(nsolM==0) |
|
159 |
{
|
|
160 |
UpdateC1((dsqM-p2_.M2())/(2.*p2_.Mt2())); |
|
161 |
UpdateC2(((dsqM-p1_.M2())/2.+p1met_)/p1_.Mt2()); |
|
162 |
// Does the larger ellipse contain the smaller one?
|
|
163 |
double dis = C2_[0]*x0*x0+2.*C2_[1]*x0*y0+C2_[2]*y0*y0+2.*C2_[3]*x0+2.*C2_[4]*y0+C2_[5]; |
|
164 |
if(dis<0) dsqH=dsqM; |
|
165 |
else dsqL=dsqM; |
|
166 |
}
|
|
167 |
} while ((dsqH-dsqL)>0.001); |
|
168 |
return false; |
|
169 |
}
|
|
170 |
||
171 |
double TransverseVariables::GetMT2() |
|
172 |
{
|
|
173 |
// massless case
|
|
174 |
if(p1_.M()<=0.1 && p2_.M()<=0.1) { return GetMT2_massless(); } |
|
175 |
||
176 |
// Solving the two quadratic equations: initialization of the coefficients
|
|
177 |
double dsq0 = p2_.M()*(p2_.M() + 2.*m_); |
|
178 |
InitCoefs(); |
|
179 |
UpdateC1( (dsq0-p2_.M2())/(2.*p2_.Mt2()) ); |
|
180 |
UpdateC2( ((dsq0-p1_.M2())/2.+p1met_)/p1_.Mt2() ); |
|
181 |
||
182 |
// Get the center of the ellipses amd check if the larger ellipse contains
|
|
183 |
// the smaller one
|
|
184 |
double x0 = (C1_[2]*C1_[3]-C1_[1]*C1_[4])/(C1_[1]*C1_[1]-C1_[0]*C1_[2]); |
|
185 |
double y0 = (C1_[0]*C1_[4]-C1_[1]*C1_[3])/(C1_[1]*C1_[1]-C1_[0]*C1_[2]); |
|
186 |
double dis= C2_[0]*x0*x0+2.*C2_[1]*x0*y0+C2_[2]*y0*y0+2.*C2_[3]*x0+2.*C2_[4]*y0+C2_[5]; |
|
187 |
if(dis<=0.01) { return sqrt(msq_+dsq0); } |
|
188 |
||
189 |
// If not, check if the larger ellipse contains the center of the smaller one
|
|
190 |
// and get two estimates for an upper bound on MT2 (dsqH)
|
|
191 |
double p2x0 = pmx_-x0, p2y0 = pmy_-y0; |
|
192 |
double dsqH = 2.*(p1_.Mt()*sqrt(pow(p2x0,2)+pow(p2y0,2)+msq_)-p1_.Px()*p2x0-p1_.Py()*p2y0) |
|
193 |
+p1_.M2(); |
|
194 |
double dsqH2 = 2.*(p1_.Mt()*sqrt(pmtm_)-p1met_)+p1_.M2(); |
|
195 |
double dsqH3 = 2.*p2_.Mt()*m_ + p2_.M2(); |
|
196 |
if(dsqH3 > dsqH2) dsqH2 = dsqH3; |
|
197 |
if(dsqH > dsqH2) dsqH = dsqH2; |
|
198 |
||
199 |
// Calculating the number of solutions: coefficients for the two quadratic equations
|
|
200 |
// bissection method
|
|
70.1.34
by Benjamin Fuks
Implementation of the MT2W variable + sorting functions |
201 |
int nsolL = Nsolutions(p2_.Mt()); |
70.1.5
by Benjamin Fuks
MT2 variable + macos change of stdc++ library (bug #1250337) + ... |
202 |
if(nsolL>0) { return sqrt(msq_+dsq0); } |
203 |
||
204 |
UpdateC1( (dsqH-p2_.M2())/(2.*p2_.Mt2()) ); |
|
205 |
UpdateC2( ((dsqH-p1_.M2())/2.+p1met_)/p1_.Mt2() ); |
|
70.1.34
by Benjamin Fuks
Implementation of the MT2W variable + sorting functions |
206 |
int nsolH = Nsolutions(p2_.Mt()); |
70.1.5
by Benjamin Fuks
MT2 variable + macos change of stdc++ library (bug #1250337) + ... |
207 |
if(nsolH==nsolL || nsolH==4) { if(!FindHigh(dsqH)) { return sqrt(dsq0+msq_); } } |
208 |
||
209 |
while(sqrt(dsqH+msq_) - sqrt(dsq0+msq_) > 0.001) |
|
210 |
{
|
|
211 |
double dsqM = (dsqH+dsq0)/2.; |
|
212 |
UpdateC1( (dsqM-p2_.M2())/(2.*p2_.Mt2()) ); |
|
213 |
UpdateC2( ((dsqM-p1_.M2())/2.+p1met_)/p1_.Mt2() ); |
|
70.1.34
by Benjamin Fuks
Implementation of the MT2W variable + sorting functions |
214 |
int nsolM = Nsolutions(p2_.Mt()); |
70.1.5
by Benjamin Fuks
MT2 variable + macos change of stdc++ library (bug #1250337) + ... |
215 |
if(nsolM==4) { dsqH=dsqM; FindHigh(dsqH); continue; } |
216 |
if(nsolM!=nsolL) dsqH=dsqM; |
|
217 |
if(nsolM==nsolL) dsq0=dsqM; |
|
218 |
}
|
|
219 |
return sqrt(msq_+dsqH); |
|
220 |
}
|
|
221 |
||
222 |
double TransverseVariables::GetMT2_massless() |
|
223 |
{
|
|
224 |
// Rotation of all four-momenta so that p2_.Py() = 0
|
|
225 |
double th=-atan(p2_.Py()/p2_.Px()); |
|
109.1.45
by Eric Conte
no more Root first step |
226 |
MARotation3axis rot(th,MARotation3axis::Zaxis); |
227 |
rot.rotate(p2_); |
|
228 |
rot.rotate(p1_); |
|
70.1.5
by Benjamin Fuks
MT2 variable + macos change of stdc++ library (bug #1250337) + ... |
229 |
double pxtmp = pmx_*cos(th)-pmy_*sin(th); |
230 |
double pytmp = sin(th)*pmx_+cos(th)*pmy_; |
|
231 |
pmx_ = pxtmp; |
|
232 |
pmy_ = pytmp; |
|
233 |
||
234 |
// Initialization of the C2 coefficients + dsq0 + proceed with the calculation
|
|
235 |
// of the number of solutions for the lower bourd
|
|
236 |
double dsq0 = 0.0005/p2_.Mt2(); |
|
237 |
InitC(p1_,C2_); |
|
238 |
UpdateC2( (dsq0+p1met_)/p1_.Mt2() ); |
|
239 |
||
240 |
// Calculating the number of solutions: coefficients for the two quadratic equations
|
|
241 |
// bissection method
|
|
242 |
int nsolL = Nsolutions_massless(dsq0); |
|
243 |
if(nsolL>0) { return sqrt(msq_+dsq0); } |
|
244 |
||
245 |
// When both parabolas contain origin: two estimates for an upper bound on MT2 (dsqH)
|
|
246 |
double dsqH = 2.*(p1_.Mt()*sqrt(pmtm_) - p1met_); |
|
247 |
double dsqH2 = 2.*m_*p2_.Mt(); |
|
248 |
if(dsqH < dsqH2) dsqH = dsqH2; |
|
249 |
||
250 |
UpdateC2( (dsqH/2.+p1met_)/p1_.Mt2() ); |
|
251 |
int nsolH = Nsolutions_massless(dsqH); |
|
252 |
||
253 |
// Scanning to get a new lower bound (bissection method)
|
|
254 |
bool found=false; |
|
255 |
if (nsolH==nsolL) |
|
256 |
{
|
|
257 |
for(double mass = m_+0.1; mass < sqrt(msq_+dsqH); mass+=0.1) |
|
258 |
{
|
|
259 |
dsqH = pow(mass,2) - msq_; |
|
260 |
UpdateC2( (dsqH/2.+p1met_)/p1_.Mt2() ); |
|
261 |
nsolH = Nsolutions_massless(dsqH); |
|
262 |
if(nsolH>0) { found=true; dsq0=pow(mass-0.1,2)-msq_; break; } |
|
263 |
}
|
|
264 |
if(!found) { return sqrt(dsq0+msq_); } |
|
265 |
}
|
|
266 |
if(nsolH==nsolL) { return sqrt(dsq0+msq_); } |
|
267 |
||
268 |
// Now we apply the bissection method
|
|
269 |
while(sqrt(dsqH+msq_) - sqrt(dsq0+msq_) > 0.001) |
|
270 |
{
|
|
271 |
double dsqM = (dsqH+dsq0)/2.; |
|
272 |
UpdateC2( (dsqM/2.+p1met_)/p1_.Mt2() ); |
|
273 |
int nsolM = Nsolutions_massless(dsqM); |
|
274 |
if(nsolM!=nsolL) dsqH=dsqM; |
|
275 |
if(nsolM==nsolL) dsq0=dsqM; |
|
276 |
}
|
|
277 |
return sqrt(dsqH+msq_); |
|
278 |
}
|
|
70.1.34
by Benjamin Fuks
Implementation of the MT2W variable + sorting functions |
279 |
|
280 |
/// -----------------------------------------------
|
|
281 |
/// Funcions related to the computation of the mt2w
|
|
282 |
/// -----------------------------------------------
|
|
283 |
/// Core function for the computation of mt2w
|
|
109.1.62
by Benjamin Fuks
logging + -no-root |
284 |
double TransverseVariables::GetMT2W(const ParticleBaseFormat* lep,const ParticleBaseFormat* j1, |
285 |
const ParticleBaseFormat*j2,const ParticleBaseFormat&met) |
|
70.1.34
by Benjamin Fuks
Implementation of the MT2W variable + sorting functions |
286 |
{
|
287 |
/// We define a mt2w region in which we will search for the bissection
|
|
288 |
/// (default: from mw+mb to 500 GeV)
|
|
109.1.62
by Benjamin Fuks
logging + -no-root |
289 |
InitializeMT2W(lep->momentum(), j1->momentum(), j2->momentum(), met.momentum()); |
70.1.34
by Benjamin Fuks
Implementation of the MT2W variable + sorting functions |
290 |
double mt_high = 500., upper=500.; |
291 |
double mt_low = mw_ + std::max(p2_.M(), p3_.M()); |
|
292 |
||
293 |
/// First, we need to check the 500 GeV hypothesis -> otherwise, we start at threshold
|
|
294 |
if(!TestComp(mt_high)) mt_high = mt_low; |
|
295 |
||
296 |
// Scan to find the upper bound
|
|
297 |
double step=0.5; |
|
298 |
while(!TestComp(mt_high) && mt_high < upper+2.*step) |
|
299 |
{
|
|
300 |
mt_low = mt_high; |
|
301 |
mt_high += step; |
|
302 |
}
|
|
303 |
||
304 |
// No compatible region found under the upper bound -> return upper bound - 1 GeV
|
|
305 |
if (mt_high > upper) { return upper-2.*step; } |
|
306 |
||
307 |
// mt_high is compatible -> bissection method
|
|
308 |
while(mt_high-mt_low>0.001) |
|
309 |
{
|
|
310 |
double mt_mid = (mt_high+mt_low)/2.; |
|
311 |
if(!TestComp(mt_mid)) mt_low = mt_mid; |
|
312 |
else mt_high = mt_mid; |
|
313 |
}
|
|
314 |
return mt_high; |
|
315 |
}
|
|
316 |
||
317 |
/// Test if for a given event, the trial top mass is compatible with the real top mass
|
|
318 |
bool TransverseVariables::TestComp(const double &mt) |
|
319 |
{
|
|
320 |
// Quick check if the trial top mass is larger than the two possible thresholds
|
|
321 |
if(mt<(p2_.M()+mw_) || mt<(p3_.M()+mw_)) { return false;} |
|
322 |
||
323 |
// Calculate the delta, delta1 and delta2 quantities
|
|
324 |
double delta = (pow(mt,2.) - mw2_ - p3_.M2())/(2.*p3_.Mt2()); |
|
325 |
double del1 = mw2_ - p1_.M2(); |
|
70.1.35
by Benjamin Fuks
Few bugs corrected in the mt2w implementation (thanks to Jeremy ... |
326 |
double del2 = pow(mt,2.) - mw2_ - p2_.M2() - 2.*plpb1_; |
70.1.34
by Benjamin Fuks
Implementation of the MT2W variable + sorting functions |
327 |
|
328 |
// Removing pbz
|
|
329 |
double aa = (p1_.E()*p2_.Px()-p2_.E()*p1_.Px())/ (p2_.E()*p1_.Pz()-p1_.E()*p2_.Pz()); |
|
330 |
double bb = (p1_.E()*p2_.Py()-p2_.E()*p1_.Py())/ (p2_.E()*p1_.Pz()-p1_.E()*p2_.Pz()); |
|
331 |
double cc = (p1_.E()*del2-p2_.E()*del1)/(2.*(p2_.E()*p1_.Pz()-p1_.E()*p2_.Pz())); |
|
332 |
||
333 |
// Computing the coefficients of the two quadratic equations
|
|
334 |
C1_.resize(0); |
|
335 |
C1_.push_back(E2sq_*(1.+pow(aa,2.))-pow(p2_.Px()+p2_.Pz()*aa,2.)); |
|
336 |
C1_.push_back(E2sq_*aa*bb-(p2_.Px()+p2_.Pz()*aa)*(p2_.Py()+p2_.Pz()*bb)); |
|
337 |
C1_.push_back(E2sq_*(1.+pow(bb,2.))-pow(p2_.Py()+p2_.Pz()*bb,2.)); |
|
338 |
C1_.push_back(E2sq_*aa*cc-(p2_.Px()+p2_.Pz()*aa)*(del2/2.+p2_.Pz()*cc)); |
|
339 |
C1_.push_back(E2sq_*bb*cc-(p2_.Py()+p2_.Pz()*bb)*(del2/2.+p2_.Pz()*cc)); |
|
340 |
C1_.push_back(E2sq_*pow(cc,2.)-pow(del2/2.+p2_.Pz()*cc,2.)); |
|
341 |
||
342 |
// Checking if the first equation admits real solutions
|
|
343 |
if( ((C1_[0]*(C1_[2]*C1_[5]-pow(C1_[4],2.))-C1_[1]*(C1_[1]*C1_[5]-C1_[3]*C1_[4])+ |
|
344 |
C1_[3]*(C1_[1]*C1_[4]-C1_[2]*C1_[3]))/(C1_[0]+C1_[2]))>0.) { return false; } |
|
345 |
||
346 |
// Defining the coefficients for the second ellipse
|
|
347 |
C2_.resize(0); |
|
348 |
C2_.push_back(1.-pow(p3_.Px(),2.)/p3_.Mt2()); |
|
349 |
C2_.push_back(-p3_.Px()*p3_.Py()/p3_.Mt2()); |
|
350 |
C2_.push_back(1.-pow(p3_.Py(),2.)/p3_.Mt2()); |
|
351 |
C2_.push_back(delta*p3_.Px()); |
|
352 |
C2_.push_back(delta*p3_.Py()); |
|
353 |
C2_.push_back(C2_[0]*pow(pmx_,2.)+2.*C2_[1]*pmx_*pmy_+C2_[2]*pow(pmy_,2.)-2.*C2_[3]*pmx_ |
|
354 |
-2.*C2_[4]*pmy_+mw2_-pow(delta,2.)*p3_.Et2()); |
|
355 |
C2_[3] += -C2_[0]*pmx_-C2_[1]*pmy_; |
|
356 |
C2_[4] += -C2_[2]*pmy_-C2_[1]*pmx_; |
|
357 |
||
358 |
// Get a point on the 1st ellipse and checks if it lies within the 2nd ellipse
|
|
359 |
// It is always possible to define (x0,y0) has ellipse 1 admits real solutions
|
|
360 |
// if True, then mt is compatible
|
|
361 |
double x0 = (C1_[2]*C1_[3]-C1_[1]*C1_[4])/(C1_[1]*C1_[1]-C1_[0]*C1_[2]); |
|
362 |
double x0sq = pow(x0,2.); |
|
363 |
double y0 = (-C1_[1]*x0-C1_[4]+ |
|
364 |
sqrt(pow(C1_[1]*x0+C1_[4],2.)-C1_[2]*(C1_[0]*x0sq+2.*C1_[3]*x0+C1_[5])))/C1_[2]; |
|
365 |
double y0sq = pow(y0,2.); |
|
366 |
if((C2_[0]*x0sq+2.*C2_[1]*x0*y0+C2_[2]*y0sq+2.*C2_[3]*x0+2.*C2_[4]*y0+C2_[5])<0.) |
|
367 |
return true; |
|
368 |
||
369 |
// Computing the number of intersections between the two ellipses and returning the
|
|
370 |
// result as a function of the number of intersections
|
|
371 |
if (Nsolutions(p2_.E())==0) { return false;} |
|
372 |
return true; |
|
373 |
}
|
|
374 |
||
375 |
||
376 |
/// Wrapper fuction for the computation of mt2w
|
|
109.1.62
by Benjamin Fuks
logging + -no-root |
377 |
double TransverseVariables::MT2W(std::vector<const RecJetFormat*> jets, const RecLeptonFormat* lep, const ParticleBaseFormat& met) |
70.1.34
by Benjamin Fuks
Implementation of the MT2W variable + sorting functions |
378 |
{
|
379 |
/// We need at least 2 jets
|
|
380 |
if(jets.size()<2) return 0.; |
|
381 |
||
382 |
/// Split the jet collection according to b-tags
|
|
383 |
std::vector<const RecParticleFormat*> bjets, nbjets; |
|
384 |
for(unsigned int ii=0 ;ii<jets.size(); ii++) |
|
385 |
{
|
|
386 |
if(jets[ii]->btag()) bjets.push_back(jets[ii]); |
|
387 |
else nbjets.push_back(jets[ii]); |
|
388 |
}
|
|
389 |
/// pt-ordering
|
|
390 |
SORTER->sort(nbjets,PTordering); |
|
391 |
SORTER->sort(bjets,PTordering); |
|
392 |
||
393 |
/// We neglect the fourth jets and all the others. If less than 3 jets in total
|
|
394 |
/// only light jets are considered.
|
|
395 |
unsigned int N=3; |
|
396 |
if(jets.size()<=3) N = nbjets.size(); |
|
397 |
||
398 |
/// no b-jets
|
|
399 |
/// We select the minimum mt2w obtained from all possible jet combinations
|
|
400 |
if(bjets.size()==0) |
|
401 |
{
|
|
402 |
double min_mt2w=1e9; |
|
403 |
for (unsigned int ii=0; ii<N; ii++) |
|
404 |
for (unsigned int jj=0; jj<N; jj++) |
|
405 |
{
|
|
406 |
if (ii==jj) continue; |
|
109.1.62
by Benjamin Fuks
logging + -no-root |
407 |
double tmp_mt2w = GetMT2W(lep, nbjets[ii], nbjets[jj],met); |
408 |
if(tmp_mt2w < min_mt2w) min_mt2w = tmp_mt2w; |
|
409 |
}
|
|
410 |
return min_mt2w; |
|
411 |
}
|
|
412 |
||
413 |
/// 1 b-jet
|
|
414 |
else if (bjets.size()==1) |
|
415 |
{
|
|
416 |
double min_mt2w=1e9; |
|
417 |
for (unsigned int ii=0; ii<N; ii++) |
|
418 |
{
|
|
419 |
double tmp_mt2w = GetMT2W(lep,bjets[0],nbjets[ii],met); |
|
420 |
if (tmp_mt2w < min_mt2w) min_mt2w = tmp_mt2w; |
|
421 |
tmp_mt2w = GetMT2W(lep,nbjets[ii],bjets[0],met); |
|
422 |
if (tmp_mt2w < min_mt2w) min_mt2w = tmp_mt2w; |
|
423 |
}
|
|
424 |
return min_mt2w; |
|
425 |
}
|
|
426 |
||
427 |
/// More than 1 b-tag
|
|
428 |
else
|
|
429 |
{
|
|
430 |
double min_mt2w=1e9; |
|
431 |
for (unsigned int ii=0; ii<bjets.size(); ii++) |
|
432 |
for (unsigned int jj=0; jj<bjets.size(); jj++) |
|
433 |
{
|
|
434 |
if (ii==jj) continue; |
|
435 |
double tmp_mt2w = GetMT2W(lep, bjets[ii], bjets[jj],met); |
|
436 |
if (tmp_mt2w < min_mt2w) min_mt2w = tmp_mt2w; |
|
437 |
}
|
|
438 |
return min_mt2w; |
|
439 |
}
|
|
440 |
}
|
|
441 |
||
442 |
double TransverseVariables::MT2W(std::vector<const MCParticleFormat*> jets, const MCParticleFormat* lep, const ParticleBaseFormat& met) |
|
443 |
{
|
|
444 |
/// We need at least 2 jets
|
|
445 |
if(jets.size()<2) return 0.; |
|
446 |
||
447 |
/// Split the jet collection according to b-tags
|
|
448 |
std::vector<const MCParticleFormat*> bjets, nbjets; |
|
449 |
for(unsigned int ii=0 ;ii<jets.size(); ii++) |
|
450 |
{
|
|
451 |
if(abs(jets[ii]->pdgid()==5)) bjets.push_back(jets[ii]); |
|
452 |
else nbjets.push_back(jets[ii]); |
|
453 |
}
|
|
454 |
/// pt-ordering
|
|
455 |
SORTER->sort(nbjets,PTordering); |
|
456 |
SORTER->sort(bjets,PTordering); |
|
457 |
||
458 |
/// We neglect the fourth jets and all the others. If less than 3 jets in total
|
|
459 |
/// only light jets are considered.
|
|
460 |
unsigned int N=3; |
|
461 |
if(jets.size()<=3) N = nbjets.size(); |
|
462 |
||
463 |
/// no b-jets
|
|
464 |
/// We select the minimum mt2w obtained from all possible jet combinations
|
|
465 |
if(bjets.size()==0) |
|
466 |
{
|
|
467 |
double min_mt2w=1e9; |
|
468 |
for (unsigned int ii=0; ii<N; ii++) |
|
469 |
for (unsigned int jj=0; jj<N; jj++) |
|
470 |
{
|
|
471 |
if (ii==jj) continue; |
|
472 |
double tmp_mt2w = GetMT2W(lep, nbjets[ii], nbjets[jj],met); |
|
473 |
if(tmp_mt2w < min_mt2w) min_mt2w = tmp_mt2w; |
|
474 |
}
|
|
475 |
return min_mt2w; |
|
476 |
}
|
|
477 |
||
478 |
/// 1 b-jet
|
|
479 |
else if (bjets.size()==1) |
|
480 |
{
|
|
481 |
double min_mt2w=1e9; |
|
482 |
for (unsigned int ii=0; ii<N; ii++) |
|
483 |
{
|
|
484 |
double tmp_mt2w = GetMT2W(lep,bjets[0],nbjets[ii],met); |
|
485 |
if (tmp_mt2w < min_mt2w) min_mt2w = tmp_mt2w; |
|
486 |
tmp_mt2w = GetMT2W(lep,nbjets[ii],bjets[0],met); |
|
487 |
if (tmp_mt2w < min_mt2w) min_mt2w = tmp_mt2w; |
|
488 |
}
|
|
489 |
return min_mt2w; |
|
490 |
}
|
|
491 |
||
492 |
/// More than 1 b-tag
|
|
493 |
else
|
|
494 |
{
|
|
495 |
double min_mt2w=1e9; |
|
496 |
for (unsigned int ii=0; ii<bjets.size(); ii++) |
|
497 |
for (unsigned int jj=0; jj<bjets.size(); jj++) |
|
498 |
{
|
|
499 |
if (ii==jj) continue; |
|
500 |
double tmp_mt2w = GetMT2W(lep, bjets[ii], bjets[jj],met); |
|
501 |
if (tmp_mt2w < min_mt2w) min_mt2w = tmp_mt2w; |
|
502 |
}
|
|
503 |
return min_mt2w; |
|
504 |
}
|
|
505 |
}
|
|
506 |
||
109.1.11
by Benjamin Fuks
updating mt2w |
507 |
|
70.1.45
by Benjamin Fuks
Splitting the physics services in subcategories |
508 |
|
509 |
/// The alphaT variable
|
|
510 |
void LoopForAlphaT(const unsigned int n1, const std::vector<const MCParticleFormat*> jets, |
|
511 |
double &MinDHT, const int last, std::vector<unsigned int> Ids) |
|
512 |
{
|
|
513 |
// We have enough information to form the pseudo jets
|
|
514 |
if(Ids.size()==n1) |
|
515 |
{
|
|
516 |
// Forming the two pseudo jets
|
|
517 |
std::vector<const MCParticleFormat*> jets1; |
|
518 |
std::vector<const MCParticleFormat*> jets2=jets; |
|
519 |
for (int j=n1-1; j>=0; j--) |
|
520 |
{
|
|
521 |
jets1.push_back(jets[Ids[j]]); |
|
522 |
jets2.erase(jets2.begin()+Ids[j]); |
|
523 |
}
|
|
524 |
||
525 |
// Computing the DeltaHT of the pseudo jets and checking if minimum
|
|
526 |
double THT1 = 0; double THT2 = 0; |
|
527 |
for (unsigned int i=0;i<jets1.size();i++) THT1+=jets1[i]->et(); |
|
528 |
for (unsigned int i=0;i<jets2.size();i++) THT2+=jets2[i]->et(); |
|
115.1.9
by Eric Conte
replace fabs by std::abs |
529 |
double DeltaHT = std::abs(THT1-THT2); |
70.1.45
by Benjamin Fuks
Splitting the physics services in subcategories |
530 |
if (DeltaHT<MinDHT) MinDHT=DeltaHT; |
531 |
||
532 |
// Exit
|
|
533 |
return; |
|
534 |
}
|
|
535 |
||
536 |
// The first pseudo jet is incomplete -> adding one element
|
|
537 |
std::vector<unsigned int> Save=Ids; |
|
538 |
for(unsigned int i=last+1; i<=jets.size()-n1+Save.size(); i++) |
|
539 |
{
|
|
540 |
Ids = Save; |
|
541 |
Ids.push_back(i); |
|
542 |
LoopForAlphaT(n1, jets, MinDHT, i, Ids); |
|
543 |
}
|
|
544 |
}
|
|
545 |
||
546 |
void LoopForAlphaT(const unsigned int n1, std::vector<RecJetFormat> jets, |
|
547 |
double &MinDHT, const int last, std::vector<unsigned int> Ids) |
|
548 |
{
|
|
549 |
// We have enough information to form the pseudo jets
|
|
550 |
if(Ids.size()==n1) |
|
551 |
{
|
|
552 |
// Forming the two pseudo jets
|
|
553 |
std::vector<RecJetFormat> jets1; |
|
554 |
std::vector<RecJetFormat> jets2=jets; |
|
555 |
for (int j=n1-1; j>=0; j--) |
|
556 |
{
|
|
557 |
jets1.push_back(jets[Ids[j]]); |
|
558 |
jets2.erase(jets2.begin()+Ids[j]); |
|
559 |
}
|
|
560 |
||
561 |
// Computing the DeltaHT of the pseudo jets and checking if minimum
|
|
562 |
double THT1 = 0; double THT2 = 0; |
|
563 |
for (unsigned int i=0;i<jets1.size();i++) THT1+=jets1[i].et(); |
|
564 |
for (unsigned int i=0;i<jets2.size();i++) THT2+=jets2[i].et(); |
|
115.1.9
by Eric Conte
replace fabs by std::abs |
565 |
double DeltaHT = std::abs(THT1-THT2); |
70.1.45
by Benjamin Fuks
Splitting the physics services in subcategories |
566 |
if (DeltaHT<MinDHT) MinDHT=DeltaHT; |
567 |
||
568 |
// Exit
|
|
569 |
return; |
|
570 |
}
|
|
571 |
||
572 |
// The first pseudo jet is incomplete -> adding one element
|
|
573 |
std::vector<unsigned int> Save=Ids; |
|
574 |
for(unsigned int i=last+1; i<=jets.size()-n1+Save.size(); i++) |
|
575 |
{
|
|
576 |
Ids = Save; |
|
577 |
Ids.push_back(i); |
|
578 |
LoopForAlphaT(n1, jets, MinDHT, i, Ids); |
|
579 |
}
|
|
580 |
}
|
|
581 |
||
582 |
double TransverseVariables::AlphaT(const MCEventFormat* event) |
|
583 |
{
|
|
584 |
std::vector<const MCParticleFormat*> jets; |
|
585 |
||
586 |
// Creating jet collection
|
|
587 |
for (unsigned int i=0;i<event->particles().size();i++) |
|
588 |
{
|
|
589 |
if (event->particles()[i].statuscode()!=event->particles()[event->particles().size()-1].statuscode()) continue; |
|
590 |
if (event->particles()[i].pdgid()!=21 && (abs(event->particles()[i].pdgid())<1 || |
|
591 |
abs(event->particles()[i].pdgid())>5)) continue; |
|
592 |
jets.push_back(&event->particles()[i]); |
|
593 |
}
|
|
594 |
||
595 |
// safety
|
|
596 |
if (jets.size()<2) return 0; |
|
597 |
||
598 |
// dijet event
|
|
109.1.45
by Eric Conte
no more Root first step |
599 |
if (jets.size()==2) return std::min(jets[0]->et(),jets[1]->et()) / |
115.1.30
by Eric Conte
remove tabs form h & cpp files |
600 |
( jets[0]->momentum()+jets[1]->momentum() ).Mt(); |
70.1.45
by Benjamin Fuks
Splitting the physics services in subcategories |
601 |
|
602 |
double MinDeltaHT = 1e6; |
|
603 |
||
604 |
// compute vectum sum of jet momenta
|
|
109.1.45
by Eric Conte
no more Root first step |
605 |
MALorentzVector q(0.,0.,0.,0.); |
70.1.45
by Benjamin Fuks
Splitting the physics services in subcategories |
606 |
for (unsigned int i=0;i<jets.size();i++) q+=jets[i]->momentum(); |
607 |
double MHT = q.Pt(); |
|
608 |
||
609 |
// compute HT
|
|
610 |
double THT = 0; |
|
611 |
for (unsigned int i=0;i<jets.size();i++) THT+=jets[i]->et(); |
|
612 |
||
613 |
// Safety
|
|
614 |
if (THT==0) return -1.; |
|
615 |
else if (MHT/THT>=1) return -1.; |
|
616 |
||
617 |
// more than 3 jets : split into 2 sets
|
|
618 |
// n1 = number of jets in the first set
|
|
619 |
// n2 = number of jets in the second set
|
|
620 |
for (unsigned int n1=1; n1<=(jets.size()/2); n1++) |
|
621 |
{
|
|
622 |
std::vector<unsigned int> DummyJet; |
|
623 |
LoopForAlphaT(n1,jets,MinDeltaHT,-1,DummyJet); |
|
624 |
}
|
|
625 |
||
626 |
// Final
|
|
627 |
return 0.5*(1.-MinDeltaHT/THT)/sqrt(1.-MHT/THT*MHT/THT); |
|
628 |
}
|
|
629 |
||
630 |
double TransverseVariables::AlphaT(const RecEventFormat* event) |
|
631 |
{
|
|
632 |
// jets
|
|
633 |
std::vector<RecJetFormat> jets = event->jets(); |
|
634 |
||
635 |
// safety
|
|
636 |
if (jets.size()<2) return 0; |
|
637 |
||
638 |
// dijet event
|
|
639 |
if (jets.size()==2) return std::min(jets[0].et(),jets[1].et()) / |
|
109.1.45
by Eric Conte
no more Root first step |
640 |
((jets[0].momentum())+(jets[1].momentum())).Mt(); |
70.1.45
by Benjamin Fuks
Splitting the physics services in subcategories |
641 |
|
642 |
double MinDeltaHT = 1e6; |
|
643 |
||
644 |
// compute vectum sum of jet momenta
|
|
109.1.45
by Eric Conte
no more Root first step |
645 |
MALorentzVector q(0.,0.,0.,0.); |
70.1.45
by Benjamin Fuks
Splitting the physics services in subcategories |
646 |
for (unsigned int i=0;i<jets.size();i++) q+=jets[i].momentum(); |
647 |
double MHT = q.Pt(); |
|
648 |
||
649 |
// compute HT
|
|
650 |
double THT = 0; |
|
651 |
for (unsigned int i=0;i<jets.size();i++) THT+=jets[i].et(); |
|
652 |
||
653 |
// Safety
|
|
654 |
if (THT==0) return -1.; |
|
655 |
else if (MHT/THT>=1) return -1.; |
|
656 |
||
657 |
// more than 3 jets : split into 2 sets
|
|
658 |
// n1 = number of jets in the first set
|
|
659 |
// n2 = number of jets in the second set
|
|
660 |
for (unsigned int n1=1; n1<=(jets.size()/2); n1++) |
|
661 |
{
|
|
662 |
std::vector<unsigned int> DummyJet; |
|
663 |
LoopForAlphaT(n1,jets,MinDeltaHT,-1,DummyJet); |
|
664 |
}
|
|
665 |
||
666 |
// Final
|
|
667 |
return 0.5*(1.-MinDeltaHT/THT)/sqrt(1.-MHT/THT*MHT/THT); |
|
668 |
}
|
|
669 |
||
670 |
||
671 |
||
672 |