New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve performance of Cellular Automaton for regional tracking at HLT #17373
Merged
Merged
Changes from 7 commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
e737ca1
code cleanup
JanFSchulte 401fea2
small fixes
JanFSchulte e049096
a bit more cleanup
JanFSchulte a5a4cdb
code cleanup
JanFSchulte f150018
code cleanup II
JanFSchulte 55922e5
last cleanup
JanFSchulte 48d82fe
another round of comments from Matti
JanFSchulte 77f9a41
adressing comments from Slava
JanFSchulte File filter
Filter by extension
Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -99,11 +99,8 @@ void CAHitQuadrupletGenerator::fillDescriptions(edm::ParameterSetDescription& de | |
void CAHitQuadrupletGenerator::initEvent(const edm::Event& ev, const edm::EventSetup& es) { | ||
if (theComparitor) theComparitor->init(ev, es); | ||
} | ||
|
||
namespace { | ||
template <typename T_HitDoublets, typename T_GeneratorOrPairsFunction> | ||
void fillGraph(const SeedingLayerSetsHits& layers, CAGraph& g, T_HitDoublets& hitDoublets, | ||
T_GeneratorOrPairsFunction generatorOrPairsFunction) { | ||
void createGraphStructure(const SeedingLayerSetsHits& layers, CAGraph& g) { | ||
for (unsigned int i = 0; i < layers.size(); i++) | ||
{ | ||
for (unsigned int j = 0; j < 4; ++j) | ||
|
@@ -131,7 +128,41 @@ namespace { | |
} | ||
|
||
} | ||
} | ||
} | ||
} | ||
void clearGraphStructure(const SeedingLayerSetsHits& layers, CAGraph& g) { | ||
g.theLayerPairs.clear(); | ||
for (unsigned int i = 0; i < g.theLayers.size(); i++ ){ | ||
g.theLayers[i].theInnerLayers.clear(); | ||
g.theLayers[i].theInnerLayerPairs.clear(); | ||
g.theLayers[i].theOuterLayers.clear(); | ||
g.theLayers[i].theOuterLayerPairs.clear(); | ||
|
||
} | ||
|
||
} | ||
template <typename T_HitDoublets, typename T_GeneratorOrPairsFunction> | ||
void fillGraph(const SeedingLayerSetsHits& layers, CAGraph& g, T_HitDoublets& hitDoublets, | ||
T_GeneratorOrPairsFunction generatorOrPairsFunction) { | ||
for (unsigned int i = 0; i < layers.size(); i++) | ||
{ | ||
for (unsigned int j = 0; j < 4; ++j) | ||
{ | ||
auto vertexIndex = 0; | ||
auto foundVertex = std::find(g.theLayers.begin(), g.theLayers.end(), | ||
layers[i][j].name()); | ||
if (foundVertex == g.theLayers.end()) | ||
{ | ||
vertexIndex = g.theLayers.size() - 1; | ||
} | ||
else | ||
{ | ||
vertexIndex = foundVertex - g.theLayers.begin(); | ||
} | ||
|
||
|
||
if (j > 0) | ||
{ | ||
|
||
auto innerVertex = std::find(g.theLayers.begin(), | ||
|
@@ -178,11 +209,12 @@ void CAHitQuadrupletGenerator::hitQuadruplets(const TrackingRegion& region, | |
|
||
CAGraph g; | ||
|
||
|
||
std::vector<HitDoublets> hitDoublets; | ||
|
||
|
||
HitPairGeneratorFromLayerPair thePairGenerator(0, 1, &theLayerCache); | ||
|
||
createGraphStructure(layers, g); | ||
fillGraph(layers, g, hitDoublets, | ||
[&](const SeedingLayerSetsHits::SeedingLayer& inner, | ||
const SeedingLayerSetsHits::SeedingLayer& outer, | ||
|
@@ -202,9 +234,8 @@ void CAHitQuadrupletGenerator::hitQuadruplets(const TrackingRegion& region, | |
hitQuadruplets(region, result, hitDoubletsPtr, g, es); | ||
theLayerCache.clear(); | ||
} | ||
|
||
void CAHitQuadrupletGenerator::hitNtuplets(const IntermediateHitDoublets::RegionLayerSets& regionLayerPairs, | ||
OrderedHitSeeds& result, | ||
void CAHitQuadrupletGenerator::hitNtuplets(const IntermediateHitDoublets& regionDoublets, | ||
std::vector<OrderedHitSeeds>& result, | ||
const edm::EventSetup& es, | ||
const SeedingLayerSetsHits& layers) { | ||
CAGraph g; | ||
|
@@ -216,21 +247,194 @@ void CAHitQuadrupletGenerator::hitNtuplets(const IntermediateHitDoublets::Region | |
SeedingLayerSetsHits::LayerIndex outer) { | ||
return pair.innerLayerIndex() == inner && pair.outerLayerIndex() == outer; | ||
}; | ||
fillGraph(layers, g, hitDoublets, | ||
[&](const SeedingLayerSetsHits::SeedingLayer& inner, | ||
const SeedingLayerSetsHits::SeedingLayer& outer, | ||
std::vector<const HitDoublets *>& hitDoublets) { | ||
using namespace std::placeholders; | ||
auto found = std::find_if(regionLayerPairs.begin(), regionLayerPairs.end(), | ||
std::bind(layerPairEqual, _1, inner.index(), outer.index())); | ||
if(found != regionLayerPairs.end()) { | ||
hitDoublets.emplace_back(&(found->doublets())); | ||
return true; | ||
} | ||
return false; | ||
}); | ||
edm::ESHandle<TrackerTopology> tTopoHand; | ||
es.get<TrackerTopologyRcd>().get(tTopoHand); | ||
const TrackerTopology *tTopo=tTopoHand.product(); | ||
|
||
const int numberOfHitsInNtuplet = 4; | ||
std::vector<CACell::CAntuplet> foundQuadruplets; | ||
|
||
|
||
|
||
int index =0; | ||
for(const auto& regionLayerPairs: regionDoublets) { | ||
|
||
const TrackingRegion& region = regionLayerPairs.region(); | ||
hitDoublets.clear(); | ||
foundQuadruplets.clear(); | ||
if (index == 0){ | ||
createGraphStructure(layers, g); | ||
} | ||
else{ | ||
clearGraphStructure(layers, g); | ||
} | ||
|
||
fillGraph(layers, g, hitDoublets, | ||
[&](const SeedingLayerSetsHits::SeedingLayer& inner, | ||
const SeedingLayerSetsHits::SeedingLayer& outer, | ||
std::vector<const HitDoublets *>& hitDoublets) { | ||
using namespace std::placeholders; | ||
auto found = std::find_if(regionLayerPairs.begin(), regionLayerPairs.end(), | ||
std::bind(layerPairEqual, _1, inner.index(), outer.index())); | ||
if(found != regionLayerPairs.end()) { | ||
hitDoublets.emplace_back(&(found->doublets())); | ||
return true; | ||
} | ||
return false; | ||
}); | ||
|
||
CellularAutomaton ca(g); | ||
|
||
ca.createAndConnectCells(hitDoublets, region, caThetaCut, | ||
caPhiCut, caHardPtCut); | ||
|
||
ca.evolve(numberOfHitsInNtuplet); | ||
|
||
ca.findNtuplets(foundQuadruplets, numberOfHitsInNtuplet); | ||
|
||
|
||
const QuantityDependsPtEval maxChi2Eval = maxChi2.evaluator(es); | ||
|
||
// re-used thoughout | ||
std::array<float, 4> bc_r; | ||
std::array<float, 4> bc_z; | ||
std::array<float, 4> bc_errZ2; | ||
std::array<GlobalPoint, 4> gps; | ||
std::array<GlobalError, 4> ges; | ||
std::array<bool, 4> barrels; | ||
bool hasAlreadyPushedACandidate = false; | ||
float selectedChi2 = std::numeric_limits<float>::max(); | ||
unsigned int previousfourthLayerId = 0; | ||
std::array<unsigned int, 2> previousCellIds ={{0,0}}; | ||
unsigned int previousSideId = 0; | ||
int previousSubDetId = 0; | ||
|
||
unsigned int numberOfFoundQuadruplets = foundQuadruplets.size(); | ||
|
||
// Loop over quadruplets | ||
for (unsigned int quadId = 0; quadId < numberOfFoundQuadruplets; ++quadId) | ||
{ | ||
|
||
auto isBarrel = [](const unsigned id) -> bool | ||
{ | ||
return id == PixelSubdetector::PixelBarrel; | ||
}; | ||
for(unsigned int i = 0; i< 3; ++i) | ||
{ | ||
auto const& ahit = foundQuadruplets[quadId][i]->getInnerHit(); | ||
gps[i] = ahit->globalPosition(); | ||
ges[i] = ahit->globalPositionError(); | ||
barrels[i] = isBarrel(ahit->geographicalId().subdetId()); | ||
} | ||
|
||
auto const& ahit = foundQuadruplets[quadId][2]->getOuterHit(); | ||
gps[3] = ahit->globalPosition(); | ||
ges[3] = ahit->globalPositionError(); | ||
barrels[3] = isBarrel(ahit->geographicalId().subdetId()); | ||
if(caOnlyOneLastHitPerLayerFilter) | ||
{ | ||
const auto fourthLayerId = tTopo->layer(ahit->geographicalId()); | ||
const auto sideId = tTopo->side(ahit->geographicalId()); | ||
const auto subDetId = ahit->geographicalId().subdetId(); | ||
const auto isTheSameTriplet = (quadId != 0) && (foundQuadruplets[quadId][0]->getCellId() == previousCellIds[0]) && (foundQuadruplets[quadId][1]->getCellId() == previousCellIds[1]); | ||
const auto isTheSameFourthLayer = (quadId != 0) && (fourthLayerId == previousfourthLayerId) && (subDetId == previousSubDetId) && (sideId == previousSideId); | ||
|
||
previousCellIds = {{foundQuadruplets[quadId][0]->getCellId(), foundQuadruplets[quadId][1]->getCellId()}}; | ||
previousfourthLayerId = fourthLayerId; | ||
|
||
|
||
if(!(isTheSameTriplet && isTheSameFourthLayer )) | ||
{ | ||
selectedChi2 = std::numeric_limits<float>::max(); | ||
hasAlreadyPushedACandidate = false; | ||
} | ||
|
||
} | ||
// TODO: | ||
// - 'line' is not used for anything | ||
// - if we decide to always do the circle fit for 4 hits, we don't | ||
// need ThirdHitPredictionFromCircle for the curvature; then we | ||
// could remove extraHitRPhitolerance configuration parameter | ||
PixelRecoLineRZ line(gps[0], gps[2]); | ||
ThirdHitPredictionFromCircle predictionRPhi(gps[0], gps[2], extraHitRPhitolerance); | ||
const float curvature = predictionRPhi.curvature(ThirdHitPredictionFromCircle::Vector2D(gps[1].x(), gps[1].y())); | ||
const float abscurv = std::abs(curvature); | ||
const float thisMaxChi2 = maxChi2Eval.value(abscurv); | ||
if (theComparitor) | ||
{ | ||
SeedingHitSet tmpTriplet(foundQuadruplets[quadId][0]->getInnerHit(), foundQuadruplets[quadId][2]->getInnerHit(), foundQuadruplets[quadId][2]->getOuterHit()); | ||
|
||
|
||
if (!theComparitor->compatible(tmpTriplet) ) | ||
{ | ||
continue; | ||
} | ||
} | ||
|
||
float chi2 = std::numeric_limits<float>::quiet_NaN(); | ||
// TODO: Do we have any use case to not use bending correction? | ||
if (useBendingCorrection) | ||
{ | ||
// Following PixelFitterByConformalMappingAndLine | ||
const float simpleCot = ( gps.back().z() - gps.front().z() ) / (gps.back().perp() - gps.front().perp() ); | ||
const float pt = 1.f / PixelRecoUtilities::inversePt(abscurv, es); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. some indentation to offset the code in the |
||
for (int i=0; i < 4; ++i) | ||
{ | ||
const GlobalPoint & point = gps[i]; | ||
const GlobalError & error = ges[i]; | ||
bc_r[i] = sqrt( sqr(point.x() - region.origin().x()) + sqr(point.y() - region.origin().y()) ); | ||
bc_r[i] += pixelrecoutilities::LongitudinalBendingCorrection(pt, es)(bc_r[i]); | ||
bc_z[i] = point.z() - region.origin().z(); | ||
bc_errZ2[i] = (barrels[i]) ? error.czz() : error.rerr(point)*sqr(simpleCot); | ||
} | ||
RZLine rzLine(bc_r, bc_z, bc_errZ2, RZLine::ErrZ2_tag()); | ||
chi2 = rzLine.chi2(); | ||
} | ||
else | ||
{ | ||
RZLine rzLine(gps, ges, barrels); | ||
chi2 = rzLine.chi2(); | ||
} | ||
if (edm::isNotFinite(chi2) || chi2 > thisMaxChi2) | ||
{ | ||
continue; | ||
|
||
} | ||
// TODO: Do we have any use case to not use circle fit? Maybe | ||
// HLT where low-pT inefficiency is not a problem? | ||
if (fitFastCircle) | ||
{ | ||
FastCircleFit c(gps, ges); | ||
chi2 += c.chi2(); | ||
if (edm::isNotFinite(chi2)) | ||
continue; | ||
if (fitFastCircleChi2Cut && chi2 > thisMaxChi2) | ||
continue; | ||
} | ||
if(caOnlyOneLastHitPerLayerFilter) | ||
{ | ||
if (chi2 < selectedChi2) | ||
{ | ||
selectedChi2 = chi2; | ||
|
||
if(hasAlreadyPushedACandidate) | ||
{ | ||
result[index].pop_back(); | ||
|
||
} | ||
result[index].emplace_back(foundQuadruplets[quadId][0]->getInnerHit(), foundQuadruplets[quadId][1]->getInnerHit(),foundQuadruplets[quadId][2]->getInnerHit(), foundQuadruplets[quadId][2]->getOuterHit()); | ||
hasAlreadyPushedACandidate = true; | ||
|
||
} | ||
} | ||
else | ||
{ | ||
result[index].emplace_back(foundQuadruplets[quadId][0]->getInnerHit(), foundQuadruplets[quadId][1]->getInnerHit(), foundQuadruplets[quadId][2]->getInnerHit(), foundQuadruplets[quadId][2]->getOuterHit()); | ||
} | ||
} | ||
index++; | ||
} | ||
|
||
hitQuadruplets(regionLayerPairs.region(), result, hitDoublets, g, es); | ||
} | ||
|
||
void CAHitQuadrupletGenerator::hitQuadruplets(const TrackingRegion& region, | ||
|
@@ -257,25 +461,19 @@ void CAHitQuadrupletGenerator::hitQuadruplets(const TrackingRegion& region, | |
|
||
const QuantityDependsPtEval maxChi2Eval = maxChi2.evaluator(es); | ||
|
||
// re-used thoughout, need to be vectors because of RZLine interface | ||
// re-used thoughout | ||
std::array<float, 4> bc_r; | ||
std::array<float, 4> bc_z; | ||
std::array<float, 4> bc_errZ2; | ||
std::array<GlobalPoint, 4> gps; | ||
std::array<GlobalError, 4> ges; | ||
std::array<bool, 4> barrels; | ||
unsigned int fourthLayerId = 0; | ||
unsigned int previousfourthLayerId = 0; | ||
int subDetId = 0; | ||
int previousSubDetId = 0; | ||
unsigned int sideId = 0; | ||
unsigned int previousSideId = 0; | ||
std::array<unsigned int, 2> previousCellIds ={{0,0}}; | ||
bool isTheSameTriplet = false; | ||
bool isTheSameFourthLayer = false; | ||
bool hasAlreadyPushedACandidate = false; | ||
float selectedChi2 = std::numeric_limits<float>::max(); | ||
|
||
unsigned int previousfourthLayerId = 0; | ||
std::array<unsigned int, 2> previousCellIds ={{0,0}}; | ||
unsigned int previousSideId = 0; | ||
int previousSubDetId = 0; | ||
|
||
unsigned int numberOfFoundQuadruplets = foundQuadruplets.size(); | ||
|
||
|
@@ -302,11 +500,11 @@ void CAHitQuadrupletGenerator::hitQuadruplets(const TrackingRegion& region, | |
|
||
if(caOnlyOneLastHitPerLayerFilter) | ||
{ | ||
fourthLayerId = tTopo->layer(ahit->geographicalId()); | ||
sideId = tTopo->side(ahit->geographicalId()); | ||
subDetId = ahit->geographicalId().subdetId(); | ||
isTheSameTriplet = (quadId != 0) && (foundQuadruplets[quadId][0]->getCellId() == previousCellIds[0]) && (foundQuadruplets[quadId][1]->getCellId() == previousCellIds[1]); | ||
isTheSameFourthLayer = (quadId != 0) && (fourthLayerId == previousfourthLayerId) && (subDetId == previousSubDetId) && (sideId == previousSideId); | ||
const auto fourthLayerId = tTopo->layer(ahit->geographicalId()); | ||
const auto sideId = tTopo->side(ahit->geographicalId()); | ||
const auto subDetId = ahit->geographicalId().subdetId(); | ||
const auto isTheSameTriplet = (quadId != 0) && (foundQuadruplets[quadId][0]->getCellId() == previousCellIds[0]) && (foundQuadruplets[quadId][1]->getCellId() == previousCellIds[1]); | ||
const auto isTheSameFourthLayer = (quadId != 0) && (fourthLayerId == previousfourthLayerId) && (subDetId == previousSubDetId) && (sideId == previousSideId); | ||
|
||
previousCellIds = {{foundQuadruplets[quadId][0]->getCellId(), foundQuadruplets[quadId][1]->getCellId()}}; | ||
previousfourthLayerId = fourthLayerId; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe use
auto&
orauto&&
to be a bit more obvious that it's not a temp copy that's modified.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added some printouts and It is clear that this loop is now doing operations on the copies.
Please fix.