1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377
|
//----------------------------------------------------------------------
// This file distributed with FastJet has been obtained from
// http://www.pa.msu.edu/~huston/Les_Houches_2005/JetClu+Midpoint-StandAlone.tgz
//
// Permission to distribute it with FastJet has been granted by Joey
// Huston (see the COPYING file in the main FastJet directory for
// details).
// Changes from the original file are listed below.
//----------------------------------------------------------------------
// History of changes compared to the original MidPointAlgorithm.cc file
//
// 2014-08-13 Matteo Cacciari and Gavin Salam
// * changed a number of int -> unsigned (and in one case
// added explicit conversion to int) to eliminate
// long-standing compiler warnings
//
// 2009-01-17 Gregory Soyez <soyez@fastjet.fr>
//
// * put the code in the fastjet::cdf namespace
//
// 2008-01-15 Gavin Salam <salam@lpthe.jussieu.fr>
//
// * put in the volatile fix for midpoint with optimization;
// checked regression test, and that speed comes out OK
//
//
// 2007-10-16 Gavin Salam <salam@lpthe.jussieu.fr>
//
// * added protection to midpoint for cases where no stable cones
// are found
//
// 2007-03-10 Gavin Salam <salam@lpthe.jussieu.fr>
//
// * added support for the pttilde scale choice in the CDF midpoint code
//
// 2007-02-21 Gavin Salam <salam@lpthe.jussieu.fr>
//
// * added option of choosing the scale used in the split-merge
// procedure (pt [default], Et or mt)
//
// 2006-09-24 Gavin Salam <salam@lpthe.jussieu.fr>
//
// * removed the local_sort method
//
// 2006-09-24 Gavin Salam <salam@lpthe.jussieu.fr>
//
// * added JetClu+MidPoint to FastJet
#include "MidPointAlgorithm.hh"
#include "ClusterComparisons.hh"
#include <algorithm>
#include <iostream>
#include <cmath>
#include <fastjet/internal/base.hh>
FASTJET_BEGIN_NAMESPACE
namespace cdf{
void MidPointAlgorithm::findStableConesFromSeeds(std::vector<PhysicsTower>& towers, std::vector<Cluster>& stableCones)
{
bool reduceConeSize = true;
for(std::vector<PhysicsTower>::iterator towerIter = towers.begin(); towerIter != towers.end(); towerIter++)
if(towerIter->fourVector.pt() > _seedThreshold)
iterateCone(towerIter->fourVector.y(),towerIter->fourVector.phi(),0,towers,stableCones,reduceConeSize);
}
void MidPointAlgorithm::findStableConesFromMidPoints(std::vector<PhysicsTower>& towers, std::vector<Cluster>& stableCones)
{
// distanceOK[i-1][j] = Is distance between stableCones i and j (i>j) less than 2*_coneRadius?
std::vector< std::vector<bool> > distanceOK;
distanceOK.resize(stableCones.size() - 1);
// MC+GPS 2014-08-13, replaced int with unsigned
for(unsigned nCluster1 = 1; nCluster1 < stableCones.size(); nCluster1++){
distanceOK[nCluster1 - 1].resize(nCluster1);
double cluster1Rapidity = stableCones[nCluster1].fourVector.y();
double cluster1Phi = stableCones[nCluster1].fourVector.phi();
// MC+GPS 2014-08-13, replaced int with unsigned
for(unsigned nCluster2 = 0; nCluster2 < nCluster1; nCluster2++){
double cluster2Rapidity = stableCones[nCluster2].fourVector.y();
double cluster2Phi = stableCones[nCluster2].fourVector.phi();
double dRapidity = fabs(cluster1Rapidity - cluster2Rapidity);
double dPhi = fabs(cluster1Phi - cluster2Phi);
if(dPhi > M_PI)
dPhi = 2*M_PI - dPhi;
double dR = sqrt(dRapidity*dRapidity + dPhi*dPhi);
distanceOK[nCluster1 - 1][nCluster2] = dR < 2*_coneRadius;
}
}
// Find all pairs (triplets, ...) of stableCones which are less than 2*_coneRadius apart from each other.
std::vector< std::vector<int> > pairs(0);
std::vector<int> testPair(0);
int maxClustersInPair = _maxPairSize;
if(!maxClustersInPair)
maxClustersInPair = stableCones.size();
addClustersToPairs(testPair,pairs,distanceOK,maxClustersInPair);
// Loop over all combinations. Calculate MidPoint. Make midPointClusters.
bool reduceConeSize = false;
// MC+GPS 2014-08-13, replaced int with unsigned
for(unsigned iPair = 0; iPair < pairs.size(); iPair++){
// Calculate rapidity, phi and pT of MidPoint.
LorentzVector midPoint(0,0,0,0);
// MC+GPS 2014-08-13, replaced int with unsigned
for(unsigned iPairMember = 0; iPairMember < pairs[iPair].size(); iPairMember++)
midPoint.add(stableCones[pairs[iPair][iPairMember]].fourVector);
iterateCone(midPoint.y(),midPoint.phi(),midPoint.pt(),towers,stableCones,reduceConeSize);
}
//sort(stableCones.begin(),stableCones.end(),ClusterPtGreater());
local_sort(stableCones); // GPS mod. to allow split-merge with various scales
}
void MidPointAlgorithm::iterateCone(volatile double startRapidity, volatile double startPhi, volatile double startPt,
std::vector<PhysicsTower>& towers, std::vector<Cluster>& stableCones, bool reduceConeSize)
{
int nIterations = 0;
bool keepJet = true;
Cluster trialCone;
double iterationConeRadius = _coneRadius;
if(reduceConeSize)
iterationConeRadius *= sqrt(_coneAreaFraction);
while(nIterations++ < _maxIterations + 1 && keepJet){
trialCone.clear();
// Find particles which should go in the cone.
if(nIterations == _maxIterations + 1)
iterationConeRadius = _coneRadius;
for(std::vector<PhysicsTower>::iterator towerIter = towers.begin(); towerIter != towers.end(); towerIter++){
double dRapidity = fabs(towerIter->fourVector.y() - startRapidity);
double dPhi = fabs(towerIter->fourVector.phi() - startPhi);
if(dPhi > M_PI)
dPhi = 2*M_PI - dPhi;
double dR = sqrt(dRapidity*dRapidity + dPhi*dPhi);
if(dR < iterationConeRadius)
trialCone.addTower(*towerIter);
}
if(!trialCone.size()) // Empty cone?
keepJet = false;
else{
if(nIterations <= _maxIterations){
volatile double endRapidity = trialCone.fourVector.y();
volatile double endPhi = trialCone.fourVector.phi();
volatile double endPt = trialCone.fourVector.pt();
// Do we have a stable cone?
if(endRapidity == startRapidity && endPhi == startPhi && endPt == startPt){
// If cone size is reduced, then do one more iteration.
nIterations = _maxIterations;
if(!reduceConeSize)
nIterations++;
}
else{
// Another iteration.
startRapidity = endRapidity;
startPhi = endPhi;
startPt = endPt;
}
}
}
}
if(keepJet){
// We have a stable cone.
bool identical = false;
for(std::vector<Cluster>::iterator stableConeIter = stableCones.begin(); stableConeIter != stableCones.end(); stableConeIter++)
if(trialCone.fourVector.isEqual(stableConeIter->fourVector))
identical = true;
if(!identical)
stableCones.push_back(trialCone);
}
}
void MidPointAlgorithm::addClustersToPairs(std::vector<int>& testPair, std::vector< std::vector<int> >& pairs,
std::vector< std::vector<bool> >& distanceOK, int maxClustersInPair)
{
// Recursively adds clusters to pairs, triplets, ... whose mid-points are then calculated.
// Find StableCone number to start with (either 0 at the beginning or last element of testPair + 1).
int nextClusterStart = 0;
if(testPair.size())
nextClusterStart = testPair.back() + 1;
// MC+GPS 2014-08-13, replaced int nextCluster with unsigned
for(unsigned nextCluster = nextClusterStart; nextCluster <= distanceOK.size(); nextCluster++){
// Is new SeedCone less than 2*_coneRadius apart from all clusters in testPair?
bool addCluster = true;
// MC+GPS 2014-08-13, replaced int iCluster with unsigned
for(unsigned iCluster = 0; iCluster < testPair.size() && addCluster; iCluster++)
if(!distanceOK[nextCluster - 1][testPair[iCluster]])
addCluster = false;
if(addCluster){
// Add it to the testPair.
testPair.push_back(nextCluster);
// If testPair is a pair, add it to pairs.
if(testPair.size() > 1)
pairs.push_back(testPair);
// If not bigger than allowed, find more clusters within 2*_coneRadius.
// GPS+MC 2014-08-13, replaced testPair.size() with int(testPair.size())
if(int(testPair.size()) < maxClustersInPair)
addClustersToPairs(testPair,pairs,distanceOK,maxClustersInPair);
// All combinations containing testPair found. Remove last element.
testPair.pop_back();
}
}
}
void MidPointAlgorithm::splitAndMerge(std::vector<Cluster>& stableCones, std::vector<Cluster>& jets)
{
bool mergingNotFinished = true;
while(mergingNotFinished){
// Sort the stable cones (highest pt first).
//sort(stableCones.begin(),stableCones.end(),ClusterPtGreater());
local_sort(stableCones);
// Start with the highest pt cone.
std::vector<Cluster>::iterator stableConeIter1 = stableCones.begin();
if(stableConeIter1 == stableCones.end()) // Stable cone list empty?
mergingNotFinished = false;
else{
bool coneNotModified = true;
// Determine whether highest pt cone has an overlap with other stable cones.
std::vector<Cluster>::iterator stableConeIter2 = stableConeIter1;
stableConeIter2++; // 2nd highest pt cone.
while(coneNotModified && stableConeIter2 != stableCones.end()){
// Calculate overlap of the two cones.
Cluster overlap;
for(std::vector<PhysicsTower>::iterator towerIter1 = stableConeIter1->towerList.begin();
towerIter1 != stableConeIter1->towerList.end();
towerIter1++){
bool isInCone2 = false;
for(std::vector<PhysicsTower>::iterator towerIter2 = stableConeIter2->towerList.begin();
towerIter2 != stableConeIter2->towerList.end();
towerIter2++)
if(towerIter1->isEqual(*towerIter2))
isInCone2 = true;
if(isInCone2)
overlap.addTower(*towerIter1);
}
if(overlap.size()){ // non-empty overlap
coneNotModified = false;
// GPS mod to allow various scale choices in split merge --------
double overlap_scale, jet2_scale;
switch(_smScale) {
case SM_pt:
overlap_scale = overlap.fourVector.pt();
jet2_scale = stableConeIter2->fourVector.pt();
break;
case SM_Et:
overlap_scale = overlap.fourVector.Et();
jet2_scale = stableConeIter2->fourVector.Et();
break;
case SM_mt:
overlap_scale = overlap.fourVector.mt();
jet2_scale = stableConeIter2->fourVector.mt();
break;
case SM_pttilde:
overlap_scale = overlap.pt_tilde;
jet2_scale = stableConeIter2->pt_tilde;
break;
default:
std::cerr << "Unrecognized value for _smScale: "
<< _smScale << std::endl;
exit(-1);
}
if(overlap_scale >= _overlapThreshold*jet2_scale){
// end of GPS modification ---------------------------
//if(overlap.fourVector.pt() >= _overlapThreshold*stableConeIter2->fourVector.pt()){
// Merge the two cones.
for(std::vector<PhysicsTower>::iterator towerIter2 = stableConeIter2->towerList.begin();
towerIter2 != stableConeIter2->towerList.end();
towerIter2++){
bool isInOverlap = false;
for(std::vector<PhysicsTower>::iterator overlapTowerIter = overlap.towerList.begin();
overlapTowerIter != overlap.towerList.end();
overlapTowerIter++)
if(towerIter2->isEqual(*overlapTowerIter))
isInOverlap = true;
if(!isInOverlap)
stableConeIter1->addTower(*towerIter2);
}
// Remove the second cone.
stableCones.erase(stableConeIter2);
}
else{
// Separate the two cones.
// Which particle goes where?
std::vector<PhysicsTower> removeFromCone1,removeFromCone2;
for(std::vector<PhysicsTower>::iterator towerIter = overlap.towerList.begin();
towerIter != overlap.towerList.end();
towerIter++){
double towerRapidity = towerIter->fourVector.y();
double towerPhi = towerIter->fourVector.phi();
// Calculate distance from cone 1.
double dRapidity1 = fabs(towerRapidity - stableConeIter1->fourVector.y());
double dPhi1 = fabs(towerPhi - stableConeIter1->fourVector.phi());
if(dPhi1 > M_PI)
dPhi1 = 2*M_PI - dPhi1;
double dRJet1 = sqrt(dRapidity1*dRapidity1 + dPhi1*dPhi1);
// Calculate distance from cone 2.
double dRapidity2 = fabs(towerRapidity - stableConeIter2->fourVector.y());
double dPhi2 = fabs(towerPhi - stableConeIter2->fourVector.phi());
if(dPhi2 > M_PI)
dPhi2 = 2*M_PI - dPhi2;
double dRJet2 = sqrt(dRapidity2*dRapidity2 + dPhi2*dPhi2);
if(dRJet1 < dRJet2)
// Particle is closer to cone 1. To be removed from cone 2.
removeFromCone2.push_back(*towerIter);
else
// Particle is closer to cone 2. To be removed from cone 1.
removeFromCone1.push_back(*towerIter);
}
// Remove particles in the overlap region from the cones to which they have the larger distance.
for(std::vector<PhysicsTower>::iterator towerIter = removeFromCone1.begin();
towerIter != removeFromCone1.end();
towerIter++)
stableConeIter1->removeTower(*towerIter);
for(std::vector<PhysicsTower>::iterator towerIter = removeFromCone2.begin();
towerIter != removeFromCone2.end();
towerIter++)
stableConeIter2->removeTower(*towerIter);
}
}
stableConeIter2++;
}
if(coneNotModified){
// Cone 1 has no overlap with any of the other cones and can become a jet.
jets.push_back(*stableConeIter1);
stableCones.erase(stableConeIter1);
}
}
}
//sort(jets.begin(),jets.end(),ClusterPtGreater());
local_sort(jets); // GPS mod. to allow split-merge with various scales
}
void MidPointAlgorithm::local_sort(std::vector<Cluster>& clusters) {
switch(_smScale) {
case SM_pt:
sort(clusters.begin(),clusters.end(),ClusterPtGreater());
break;
case SM_Et:
sort(clusters.begin(),clusters.end(),ClusterFourVectorEtGreater());
break;
case SM_mt:
sort(clusters.begin(),clusters.end(),ClusterMtGreater());
break;
case SM_pttilde:
sort(clusters.begin(),clusters.end(),ClusterPtTildeGreater());
break;
default:
std::cerr << "Unrecognized value for _smScale: " << _smScale << std::endl;
exit(-1);
}
}
void MidPointAlgorithm::run(std::vector<PhysicsTower>& towers, std::vector<Cluster>& jets)
{
std::vector<Cluster> stableCones;
findStableConesFromSeeds(towers,stableCones);
// GPS addition to prevent crashes if no stable cones
// are found (e.g. all particles below seed threshold)
if (stableCones.size() > 0) {
findStableConesFromMidPoints(towers,stableCones);
splitAndMerge(stableCones,jets);
}
}
} // namespace cdf
FASTJET_END_NAMESPACE
|