Page Menu
Home
HEPForge
Search
Configure Global Search
Log In
Files
F10227311
JetsWithoutJets.cc
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
22 KB
Subscribers
None
JetsWithoutJets.cc
View Options
// JetsWithoutJets Package
// Questions/Comments? danbert@mit.edu jthaler@mit.edu
//
// Copyright (c) 2013
// Daniele Bertolini and Jesse Thaler
//
// $Id: $
//----------------------------------------------------------------------
// This file is part of FastJet contrib.
//
// It is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the
// Free Software Foundation; either version 2 of the License, or (at
// your option) any later version.
//
// It is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
// License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this code. If not, see <http://www.gnu.org/licenses/>.
//----------------------------------------------------------------------
#include
"JetsWithoutJets.hh"
#include
<sstream>
using
namespace
std
;
FASTJET_BEGIN_NAMESPACE
// defined in fastjet/internal/base.hh
namespace
jwj
{
//////
//
// ParticleStorage
//
//////
// find distance in rapidity-azimuth plane between this particle and other
double
ParticleStorage
::
deltaRsq
(
const
ParticleStorage
&
other
)
const
{
double
deltaRap
=
rap
()
-
other
.
rap
();
double
deltaPhi
=
abs
(
phi
()
-
other
.
phi
());
if
(
deltaPhi
>
pi
)
deltaPhi
=
twopi
-
deltaPhi
;
return
(
deltaRap
*
deltaRap
+
deltaPhi
*
deltaPhi
);
}
//////
//
// LocalStorage
//
//////
// Creates storage array
void
LocalStorage
::
establishStorage
(
const
std
::
vector
<
ParticleStorage
>
&
myParticles
,
double
Rjet
,
double
ptcut
)
{
// set radius and ptcut
_Rjet
=
Rjet
;
_ptcut
=
ptcut
;
// Dividing up Phase Space to bins of (approximate) size 2R by 2R
// Actually makes bins of size bigger than 2R by 2R such that /
// we have equal spacing of regions.
// (This index scheme need to be synced with getRapIndex/getPhiIndex)
_maxRapIndex
=
(
int
)
floor
((
_rapmax
)
/
_Rjet
);
// 2 rapmax / 2 Rjet
_rapSpread
=
2.0
*
_rapmax
/
(
floor
((
_rapmax
)
/
_Rjet
));
_maxPhiIndex
=
(
int
)
floor
((
M_PI
)
/
_Rjet
);
// 2 pi / 2 Rjet
_phiSpread
=
2.0
*
M_PI
/
(
floor
((
M_PI
)
/
_Rjet
));
// Initializing storage
_regionStorage
.
resize
(
_maxRapIndex
);
_aboveCutBool
.
resize
(
_maxRapIndex
);
for
(
int
rapIndex
=
0
;
rapIndex
<
_maxRapIndex
;
rapIndex
++
)
{
_regionStorage
[
rapIndex
].
resize
(
_maxPhiIndex
);
_aboveCutBool
[
rapIndex
].
resize
(
_maxPhiIndex
);
for
(
int
phiIndex
=
0
;
phiIndex
<
_maxPhiIndex
;
phiIndex
++
)
{
_regionStorage
[
rapIndex
][
phiIndex
].
clear
();
}
}
// looping through particles and assigning to bins
for
(
unsigned
int
i
=
0
;
i
<
myParticles
.
size
();
i
++
)
{
double
rap
=
myParticles
[
i
].
rap
();
double
phi
=
myParticles
[
i
].
phi
();
// find index for particle
int
lowRap
=
(
int
)
floor
((
rap
+
_rapmax
)
/
_rapSpread
);
int
highRap
=
(
int
)
ceil
((
rap
+
_rapmax
)
/
_rapSpread
);
int
lowPhi
=
(
int
)
floor
(
phi
/
_phiSpread
);
int
highPhi
=
(
int
)
ceil
(
phi
/
_phiSpread
);
if
(
highPhi
>=
_maxPhiIndex
)
highPhi
=
highPhi
-
_maxPhiIndex
;
// loop around
// if out of bounds, set to be in bounds.
if
(
lowRap
<
0
)
lowRap
=
0
;
if
(
lowRap
>=
_maxRapIndex
)
lowRap
=
_maxRapIndex
-
1
;
if
(
highRap
<
0
)
highRap
=
0
;
if
(
highRap
>=
_maxRapIndex
)
highRap
=
_maxRapIndex
-
1
;
// Fill in storage. For particles at periphery in rapidity, only fill two bins instead of four. If phi overlaps, do the same thing.
_regionStorage
[
lowRap
][
lowPhi
].
push_back
(
i
);
if
(
lowPhi
!=
highPhi
)
_regionStorage
[
lowRap
][
highPhi
].
push_back
(
i
);
if
(
lowRap
!=
highRap
)
_regionStorage
[
highRap
][
lowPhi
].
push_back
(
i
);
if
(
lowRap
!=
highRap
&&
lowPhi
!=
highPhi
)
_regionStorage
[
highRap
][
highPhi
].
push_back
(
i
);
}
// store whether above ptCut values
for
(
int
rapIndex
=
0
;
rapIndex
<
_maxRapIndex
;
rapIndex
++
)
{
for
(
int
phiIndex
=
0
;
phiIndex
<
_maxPhiIndex
;
phiIndex
++
)
{
_aboveCutBool
[
rapIndex
][
phiIndex
]
=
(
getSumPt
(
myParticles
,
_regionStorage
[
rapIndex
][
phiIndex
])
>=
ptcut
);
}
}
}
// What is the rapidity index? (Sync with LocalStorage::establishStorage)
int
LocalStorage
::
getRapIndex
(
const
ParticleStorage
&
myParticle
)
const
{
double
rap
=
myParticle
.
rap
();
int
rapIndex
=
round
((
rap
+
_rapmax
)
/
_rapSpread
);
if
(
rapIndex
<
0
)
rapIndex
=
0
;
if
(
rapIndex
>=
_maxRapIndex
)
rapIndex
=
_maxRapIndex
-
1
;
return
rapIndex
;
}
// what is the phi index? (Sync with LocalStorage::establishStorage)
int
LocalStorage
::
getPhiIndex
(
const
ParticleStorage
&
myParticle
)
const
{
double
phi
=
myParticle
.
phi
();
int
phiIndex
=
round
(
phi
/
_phiSpread
);
if
(
phiIndex
>=
_maxPhiIndex
)
phiIndex
=
phiIndex
-
_maxPhiIndex
;
return
phiIndex
;
}
const
vector
<
unsigned
int
>
&
LocalStorage
::
getStorageFor
(
const
ParticleStorage
&
myParticle
)
const
{
return
_regionStorage
[
getRapIndex
(
myParticle
)][
getPhiIndex
(
myParticle
)];
}
bool
LocalStorage
::
aboveCutFor
(
const
ParticleStorage
&
myParticle
)
{
return
_aboveCutBool
[
getRapIndex
(
myParticle
)][
getPhiIndex
(
myParticle
)];
}
double
LocalStorage
::
getSumPt
(
const
std
::
vector
<
ParticleStorage
>
&
Particles
,
const
std
::
vector
<
unsigned
int
>
myIds
)
const
{
double
myPt
=
0
;
for
(
unsigned
int
i
=
0
;
i
<
myIds
.
size
();
i
++
)
myPt
+=
Particles
[
myIds
[
i
]].
pt
();
return
myPt
;
}
//////
//
// EventStorage
//
//////
// build a ParticleStorage for each particle and store default info,
// also build an internal vector containing particle indices (need this in _establishDerivedStorage())
void
EventStorage
::
_establishBasicStorage
(
const
std
::
vector
<
PseudoJet
>
&
particles
){
_storage
.
resize
(
0
);
_ids
.
resize
(
0
);
for
(
unsigned
int
i
=
0
;
i
<
particles
.
size
();
i
++
){
ParticleStorage
myParticleStorage
(
particles
[
i
]);
_storage
.
push_back
(
myParticleStorage
);
_ids
.
push_back
(
i
);
}
}
// calculate local info and store it back in ParticleStorage.
// Right now this is calculating and storing by default pt_in_Rjet, pt_in_Rsub,m_in_Rjet,and the weight=pt/pt_in_Rjet.
// A single EventStorage can be shared by multiple JetLikeEventShapes to reduce computation time.
// If bool flag _storeNeighbours==true it will also store a vector of indices corresponing to particles within a distance Rjet.
void
EventStorage
::
_establishDerivedStorage
()
{
LocalStorage
myLocalStorage
;
// if requested establish LocalStorage (use info from _storage to do so)
if
(
_useLocalStorage
)
myLocalStorage
.
establishStorage
(
_storage
,
_Rjet
,
_ptcut
);
// myLocalRegion defines a region of interest where to look for
// the neighbourhood (i.e. Rjet/Rsub circles) of the particle.
// By default it is the whole event, it will be reduced to a smaller 2Rjet by 2Rjet region by LocalStorage
const
vector
<
unsigned
int
>*
myLocalRegion
=
&
_ids
;
for
(
unsigned
int
i
=
0
;
i
<
_storage
.
size
();
i
++
){
double
pt_in_Rjet
,
pt_in_Rsub
,
m_in_Rjet
;
vector
<
unsigned
int
>
neighbours
;
_storage
[
i
].
set_includeParticle
(
false
);
if
(
_useLocalStorage
)
{
// start from rapidity/phi blocks
if
(
!
myLocalStorage
.
aboveCutFor
(
_storage
[
i
]))
continue
;
//don't do any further analysis if not above jet pTcut
// if using local storage (and the region is above ptcut) then region of interest
// where to look for the neighbourhood (i.e. Rjet/Rsub circles) of the particle is
// given by the local storage (2R_jet by 2R_jet region)
else
myLocalRegion
=
&
myLocalStorage
.
getStorageFor
(
_storage
[
i
]);
}
_get_local_info
(
i
,
myLocalRegion
,
pt_in_Rjet
,
pt_in_Rsub
,
m_in_Rjet
,
neighbours
);
// See if there is enough pt in the neighborhood to pass _ptcut
if
(
pt_in_Rjet
<
_ptcut
)
continue
;
assert
(
_Rsub
<=
_Rjet
);
if
(
pt_in_Rsub
/
pt_in_Rjet
<
_fcut
)
continue
;
_storage
[
i
].
set_includeParticle
(
true
);
_storage
[
i
].
set_pt_in_Rjet
(
pt_in_Rjet
);
_storage
[
i
].
set_pt_in_Rsub
(
pt_in_Rsub
);
_storage
[
i
].
set_m_in_Rjet
(
m_in_Rjet
);
_storage
[
i
].
set_neighbours
(
neighbours
);
_storage
[
i
].
set_weight
(
_storage
[
i
].
pt
()
/
pt_in_Rjet
);
}
}
// helper function to calculate local info around each particle. myLocalregion tells where to look, either the whole set of particles or a 2Rx2R
// local region if LocalStorage is in use
void
EventStorage
::
_get_local_info
(
const
unsigned
int
id
,
const
vector
<
unsigned
int
>*
myLocalRegion
,
double
&
pt_in_Rjet
,
double
&
pt_in_Rsub
,
double
&
m_in_Rjet
,
std
::
vector
<
unsigned
int
>
&
neighbours
)
const
{
double
Rjetsq
=
_Rjet
*
_Rjet
;
double
Rsubsq
=
_Rsub
*
_Rsub
;
pt_in_Rjet
=
0.0
;
pt_in_Rsub
=
0.0
;
m_in_Rjet
=
0.0
;
neighbours
.
resize
(
0
);
PseudoJet
pj_in_Rjet
(
0.0
,
0.0
,
0.0
,
0.0
);
for
(
unsigned
int
i
=
0
;
i
<
myLocalRegion
->
size
();
i
++
){
double
deltaRsq
=
_storage
[
id
].
deltaRsq
(
_storage
[
myLocalRegion
->
at
(
i
)]);
if
(
deltaRsq
<=
Rjetsq
)
{
pt_in_Rjet
+=
_storage
[
myLocalRegion
->
at
(
i
)].
pt
();
pj_in_Rjet
+=
_storage
[
myLocalRegion
->
at
(
i
)].
pseudoJet
();
if
(
_storeNeighbours
)
neighbours
.
push_back
(
myLocalRegion
->
at
(
i
));
if
(
deltaRsq
<=
Rsubsq
)
pt_in_Rsub
+=
_storage
[
myLocalRegion
->
at
(
i
)].
pt
();
}
}
m_in_Rjet
=
pj_in_Rjet
.
m
();
}
//////
//
// Shape Trimming
//
//////
//----------------------------------------------------------------------
// Helper for SelectorShapeTrimming.
// Class derived from SelectorWorker: pass, terminator, applies_jet_by_jet, and description are overloaded.
// It can't be applied to an individual jet since it requires information about the neighbourhood of the jet.
class
SW_ShapeTrimming
:
public
SelectorWorker
{
private
:
double
_Rjet
,
_ptcut
,
_Rsub
,
_fcut
;
bool
_useLocalStorage
;
public
:
SW_ShapeTrimming
(
double
Rjet
,
double
ptcut
,
double
Rsub
,
double
fcut
,
bool
useLocalStorage
=
true
)
:
_Rjet
(
Rjet
),
_ptcut
(
ptcut
),
_Rsub
(
Rsub
),
_fcut
(
fcut
),
_useLocalStorage
(
useLocalStorage
)
{};
virtual
bool
pass
(
const
PseudoJet
&
)
const
{
if
(
!
applies_jet_by_jet
())
throw
Error
(
"Cannot apply this selector worker to an individual jet"
);
return
false
;
}
virtual
void
terminator
(
vector
<
const
PseudoJet
*>
&
jets
)
const
{
// Copy pointers content to a vector of PseudoJets. Check if the pointer has been already nullified.
vector
<
PseudoJet
>
my_jets
;
vector
<
unsigned
int
>
indices
;
for
(
unsigned
int
i
=
0
;
i
<
jets
.
size
();
i
++
){
if
(
jets
[
i
]){
indices
.
push_back
(
i
);
my_jets
.
push_back
(
*
jets
[
i
]);
}
}
EventStorage
myEventStorage
(
_Rjet
,
_ptcut
,
_Rsub
,
_fcut
,
_useLocalStorage
,
false
);
myEventStorage
.
establishStorage
(
my_jets
);
for
(
unsigned
int
i
=
0
;
i
<
myEventStorage
.
size
();
i
++
){
if
(
!
myEventStorage
[
i
].
includeParticle
())
{
jets
[
indices
[
i
]]
=
NULL
;
continue
;
}
}
}
virtual
bool
applies_jet_by_jet
()
const
{
return
false
;}
std
::
string
jetParameterString
()
const
{
std
::
stringstream
stream
;
stream
<<
"R_jet="
<<
_Rjet
<<
", pT_cut="
<<
_ptcut
<<
", R_sub="
<<
_Rsub
<<
", fcut="
<<
_fcut
;
return
stream
.
str
();
}
virtual
string
description
()
const
{
return
"Shape trimmer, "
+
jetParameterString
();
}
};
//----------------------------------------------------------------------
// Helper for SelectorJetShapeTrimming.
// Class derived from SelectorWorker: pass, terminator, applies_jet_by_jet, and description are overloaded.
// This cannot be applied to an individual jet.
class
SW_JetShapeTrimming
:
public
SelectorWorker
{
private
:
double
_Rsub
,
_fcut
;
public
:
SW_JetShapeTrimming
(
double
Rsub
,
double
fcut
)
:
_Rsub
(
Rsub
),
_fcut
(
fcut
)
{};
virtual
bool
pass
(
const
PseudoJet
&
)
const
{
if
(
!
applies_jet_by_jet
())
throw
Error
(
"Cannot apply this selector worker to an individual jet"
);
return
false
;
}
virtual
void
terminator
(
vector
<
const
PseudoJet
*>
&
jets
)
const
{
// Copy pointers content to a vector of PseudoJets. Check if the pointer has been already nullified.
vector
<
PseudoJet
>
my_jets
;
vector
<
unsigned
int
>
indices
;
for
(
unsigned
int
i
=
0
;
i
<
jets
.
size
();
i
++
){
if
(
jets
[
i
]){
indices
.
push_back
(
i
);
my_jets
.
push_back
(
*
jets
[
i
]);
}
}
FunctionScalarPtSum
sumPt
=
FunctionScalarPtSum
();
// take sum pt of given jet
double
pt_Rjet
=
sumPt
(
my_jets
);
EventStorage
myJetStorage
(
_Rsub
,
pt_Rjet
*
_fcut
,
_Rsub
,
1.0
,
false
,
false
);
myJetStorage
.
establishStorage
(
my_jets
);
for
(
unsigned
int
i
=
0
;
i
<
myJetStorage
.
size
();
i
++
){
if
(
!
myJetStorage
[
i
].
includeParticle
())
{
jets
[
indices
[
i
]]
=
NULL
;
continue
;
}
}
}
virtual
bool
applies_jet_by_jet
()
const
{
return
false
;}
std
::
string
jetParameterString
()
const
{
std
::
stringstream
stream
;
stream
<<
"R_sub="
<<
_Rsub
<<
", fcut="
<<
_fcut
;
return
stream
.
str
();
}
virtual
string
description
()
const
{
return
"Jet shape trimmer, "
+
jetParameterString
();
}
};
Selector
SelectorShapeTrimming
(
double
Rjet
,
double
ptcut
,
double
Rsub
,
double
fcut
){
return
Selector
(
new
SW_ShapeTrimming
(
Rjet
,
ptcut
,
Rsub
,
fcut
));
}
Selector
SelectorJetShapeTrimming
(
double
Rsub
,
double
fcut
){
return
Selector
(
new
SW_JetShapeTrimming
(
Rsub
,
fcut
));
}
//////
//
// Multiple pT_cut values
//
//////
// helper to sort a vector of vector<double> by comparing just the first entry.
bool
_mySortFunction
(
std
::
vector
<
double
>
v_0
,
std
::
vector
<
double
>
v_1
)
{
return
(
v_0
[
0
]
>
v_1
[
0
]);
}
// As described in the appendix of the physics paper, one can construct the inverse
// of an event shape with respect to pT by calculating all of the possible pTi,R values and sorting them.
// This helper function accomplishes that task.
void
JetLikeEventShape_MultiplePtCutValues
::
_storeLocalInfo
(
const
std
::
vector
<
PseudoJet
>
particles
)
{
EventStorage
myEventStorage
(
_Rjet
,
0.0
,
_Rsub
,
_fcut
,
_useLocalStorage
);
myEventStorage
.
establishStorage
(
particles
);
_functionArray
.
resize
(
0
);
for
(
unsigned
int
i
=
0
;
i
<
myEventStorage
.
size
();
i
++
){
std
::
vector
<
double
>
point
(
2
);
point
[
0
]
=
myEventStorage
[
i
].
pt_in_Rjet
();
point
[
1
]
=
myEventStorage
[
i
].
weight
()
*
_measurement
->
result
(
myEventStorage
.
particles_near_to
(
i
));
_functionArray
.
push_back
(
point
);
}
}
void
JetLikeEventShape_MultiplePtCutValues
::
_buildStepFunction
()
{
std
::
sort
(
_functionArray
.
begin
(),
_functionArray
.
end
(),
_mySortFunction
);
// Calculating the cumulative sum of the measurements up to a given pt value
if
(
!
_functionArray
.
empty
()){
for
(
unsigned
int
i
=
1
;
i
<
_functionArray
.
size
();
i
++
)
_functionArray
[
i
][
1
]
+=
_functionArray
[
i
-
1
][
1
];
}
}
// helper to compare in a vector of vector<double> the first entry with an external val
bool
_myCompFunction_0
(
std
::
vector
<
double
>
v
,
double
val
)
{
return
(
v
[
0
]
<
val
);
}
// get the event shape for a given ptcut
double
JetLikeEventShape_MultiplePtCutValues
::
eventShapeFor
(
const
double
ptcut_0
)
const
{
double
eventShape
=
0.0
;
if
(
ptcut_0
<=
_functionArray
.
front
()[
0
])
eventShape
=
(
*
lower_bound
(
_functionArray
.
rbegin
(),
_functionArray
.
rend
(),
ptcut_0
,
_myCompFunction_0
))[
1
];
return
(
eventShape
);
}
// helper to compare in a vector of vector<double> the second entry with an external val
bool
_myCompFunction_1
(
std
::
vector
<
double
>
v
,
double
val
)
{
return
(
v
[
1
]
<
val
);
}
// get the ptcut for a given event shape
double
JetLikeEventShape_MultiplePtCutValues
::
ptCutFor
(
const
double
eventShape_0
)
const
{
double
ptcut
=
0.0
;
double
new_eventShape_0
=
eventShape_0
-
_offset
;
if
(
new_eventShape_0
<=
0
||
new_eventShape_0
>
_functionArray
.
back
()[
1
]
)
{
throw
Error
(
"Event shape value not valid"
);
}
else
ptcut
=
(
*
lower_bound
(
_functionArray
.
begin
(),
_functionArray
.
end
(),
new_eventShape_0
,
_myCompFunction_1
))[
0
];
return
(
ptcut
);
}
//////
//
// Njet with multiple R_jet
//
//////
// Similar to the same named function in JetLikeEventShape_MultiplePtCutValues, except now we have
// to store a lot more information.
void
ShapeJetMultiplicity_MultipleRValues
::
_buildStepFunction
(
const
std
::
vector
<
PseudoJet
>
particles
)
{
EventStorage
myEventStorage
(
_Rsub
,
0.0
,
_Rsub
,
1.0
,
false
,
false
);
myEventStorage
.
establishStorage
(
particles
);
unsigned
int
N
=
myEventStorage
.
size
();
std
::
vector
<
std
::
vector
<
double
>
>
myValues
;
myValues
.
resize
(
0
);
for
(
unsigned
int
i
=
0
;
i
<
N
;
i
++
)
{
unsigned
int
j
=
i
+
1
;
while
(
j
<
N
)
{
vector
<
double
>
myPair
(
3
);
myPair
[
0
]
=
sqrt
(
myEventStorage
[
i
].
deltaRsq
(
myEventStorage
[
j
]));
myPair
[
1
]
=
i
;
myPair
[
2
]
=
j
;
myValues
.
push_back
(
myPair
);
j
++
;
}
}
std
::
sort
(
myValues
.
begin
(),
myValues
.
end
(),
_mySortFunction
);
_functionArray
.
clear
();
_functionArray
.
resize
(
myValues
.
size
());
// Initialize
double
_tot_pt
=
0.0
;
for
(
unsigned
int
i
=
0
;
i
<
N
;
i
++
)
_tot_pt
+=
myEventStorage
[
i
].
pt
();
std
::
vector
<
double
>
pTR
(
N
);
std
::
fill
(
pTR
.
begin
(),
pTR
.
end
(),
_tot_pt
);
if
(
_trim
)
{
std
::
vector
<
double
>
pTRsub
;
for
(
unsigned
int
i
=
0
;
i
<
N
;
i
++
)
pTRsub
.
push_back
(
myEventStorage
[
i
].
pt_in_Rsub
());
for
(
unsigned
int
i
=
0
;
i
<
myValues
.
size
();
i
++
)
{
_functionArray
[
i
].
push_back
(
myValues
[
i
][
0
]);
int
id1
=
(
int
)
myValues
[
i
][
1
];
int
id2
=
(
int
)
myValues
[
i
][
2
];
pTR
[
id1
]
-=
myEventStorage
[
id2
].
pt
();
pTR
[
id2
]
-=
myEventStorage
[
id1
].
pt
();
double
myEventShape
=
0
;
for
(
unsigned
int
j
=
0
;
j
<
N
;
j
++
)
{
if
(
pTR
[
j
]
>=
_ptcut
&&
pTRsub
[
j
]
/
pTR
[
j
]
>=
_fcut
)
myEventShape
+=
myEventStorage
[
j
].
pt
()
/
pTR
[
j
];
}
_functionArray
[
i
].
push_back
(
myEventShape
);
}
}
else
{
for
(
unsigned
int
i
=
0
;
i
<
myValues
.
size
();
i
++
)
{
_functionArray
[
i
].
push_back
(
myValues
[
i
][
0
]);
unsigned
int
id1
=
(
int
)
myValues
[
i
][
1
];
unsigned
int
id2
=
(
int
)
myValues
[
i
][
2
];
pTR
[
id1
]
-=
myEventStorage
[
id2
].
pt
();
pTR
[
id2
]
-=
myEventStorage
[
id1
].
pt
();
double
myEventShape
=
0
;
for
(
unsigned
int
j
=
0
;
j
<
N
;
j
++
)
{
if
(
pTR
[
j
]
>=
_ptcut
)
myEventShape
+=
myEventStorage
[
j
].
pt
()
/
pTR
[
j
];
}
_functionArray
[
i
].
push_back
(
myEventShape
);
}
}
myValues
.
clear
();
}
// returns event shape for a given Rjet value
double
ShapeJetMultiplicity_MultipleRValues
::
eventShapeFor
(
const
double
Rjet_0
)
const
{
double
eventShape
=
0.0
;
if
(
Rjet_0
<
_Rsub
)
throw
Error
(
"Rjet < Rsub"
);
else
if
(
Rjet_0
<
0
)
throw
Error
(
"Negative Rjet"
);
else
if
(
Rjet_0
>
_functionArray
.
front
()[
0
]
)
eventShape
=
_functionArray
.
front
()[
1
];
else
eventShape
=
(
*
lower_bound
(
_functionArray
.
rbegin
(),
_functionArray
.
rend
(),
Rjet_0
,
_myCompFunction_0
))[
1
];
return
(
eventShape
);
}
//////
//
// Finding Jet Axes with the Event Shape Density
//
//////
// Find the local axes in a region of size R around each particle
void
EventShapeDensity_JetAxes
::
_find_local_axes
(
const
std
::
vector
<
PseudoJet
>
&
particles
)
{
_myParticles
=
particles
;
_N
=
particles
.
size
();
_axes
.
resize
(
0
);
_Njet_weights
.
resize
(
0
);
_pt_weights
.
resize
(
0
);
// Indexing particles (note that this is happening internally, so shouldn't modify user input)
for
(
unsigned
int
i
=
0
;
i
<
_N
;
i
++
)
_myParticles
[
i
].
set_user_index
(
i
);
EventStorage
myEventStorage
(
_Rjet
,
_ptcut
,
_Rjet
,
1.0
,
_useLocalStorage
);
myEventStorage
.
establishStorage
(
_myParticles
);
// Find axis associated with each particle.
for
(
unsigned
int
i
=
0
;
i
<
_N
;
i
++
)
{
//Recombiner has to carry user_index information.
FunctionJetAxis
axis
(
_jetDef
);
vector
<
PseudoJet
>
near_particles
=
myEventStorage
.
particles_near_to
(
i
);
int
myAxis
=
-
1
;
double
pt_w
=
0
;
double
Njet_w
=
0
;
if
(
myEventStorage
[
i
].
includeParticle
())
{
myAxis
=
axis
(
near_particles
).
user_index
();
pt_w
=
myEventStorage
[
i
].
pt
();
Njet_w
=
myEventStorage
[
i
].
weight
();
}
_axes
.
push_back
(
myAxis
);
_pt_weights
.
push_back
(
pt_w
);
_Njet_weights
.
push_back
(
Njet_w
);
}
}
// Take the axes calculated by _find_local_axes and figure out what the final
// global axes will be. With the global consistency condition, this decreases
// the number of axes under consideration.
void
EventShapeDensity_JetAxes
::
find_axes_and_weights
()
{
//If requested establish global consistency.
//Loop over axes and reassign unstable axes until no unstable axis is left.
if
(
_applyGlobalConsistency
)
{
int
n_unstable_axes
;
do
{
n_unstable_axes
=
0
;
for
(
unsigned
int
i
=
0
;
i
<
_N
;
i
++
)
{
if
(
_axes
[
i
]
!=
-
1
&&
!
_isStable
(
_axes
[
i
])){
n_unstable_axes
++
;
_axes
[
i
]
=
_axes
[
_axes
[
i
]];
}
}
}
while
(
n_unstable_axes
>
0
);
}
//Find distinct axes.
//Output a vector of Pseudojets (sorted by pT), with pT of each axis corresponding to the pT weight.
vector
<
double
>
tot_Njet_weights
(
_N
,
0
),
tot_pt_weights
(
_N
,
0
);
for
(
unsigned
int
i
=
0
;
i
<
_N
;
i
++
)
{
if
(
_axes
[
i
]
!=
-
1
)
{
tot_pt_weights
[
_axes
[
i
]]
+=
_pt_weights
[
i
];
tot_Njet_weights
[
_axes
[
i
]]
+=
_Njet_weights
[
i
];
}
}
_distinctAxes
.
resize
(
0
);
_tot_Njet_weights
.
resize
(
0
);
for
(
unsigned
int
i
=
0
;
i
<
_N
;
i
++
){
if
(
tot_pt_weights
[
i
]
>
0
)
{
PseudoJet
myAxis
=
_lightLikeVersion
(
_myParticles
[
i
])
*
tot_pt_weights
[
i
];
_distinctAxes
.
push_back
(
myAxis
);
}
}
_distinctAxes
=
sorted_by_pt
(
_distinctAxes
);
//Find the corresponding N_jet weights.
for
(
unsigned
int
i
=
0
;
i
<
_distinctAxes
.
size
();
i
++
)
_tot_Njet_weights
.
push_back
(
tot_Njet_weights
[
_distinctAxes
[
i
].
user_index
()]);
}
// Check stability: a particle defines a stable wta axis if it is its own wta or if it is pointing to a particle that does not pass pTcut.
bool
EventShapeDensity_JetAxes
::
_isStable
(
const
int
thisAxis
)
const
{
bool
answer
=
false
;
if
(
_axes
[
thisAxis
]
==
thisAxis
||
_axes
[
thisAxis
]
==
-
1
)
answer
=
true
;
return
(
answer
);
}
}
// namespace jwj
FASTJET_END_NAMESPACE
File Metadata
Details
Attached
Mime Type
text/x-c++
Expires
Thu, Apr 3, 8:07 PM (22 h, 17 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
4729193
Default Alt Text
JetsWithoutJets.cc (22 KB)
Attached To
rFASTJETSVN fastjetsvn
Event Timeline
Log In to Comment