Skip to content

Commit 828a75d

Browse files
authored
Update ParticleFlow.cxx
Added linking between Track and HCal cluster Added and refined arbitration for Track and HCal cluster matching I've implemented these algorithms as part of my bachelor degree project and I have written them very similar to the ones for the track + ecal cluster matching. I tried to stick to the existing variable "convention" but think that they might need some refinement at a later stage as "Calo" and "HadCalo" sound confusingly similar to describe the ECal and HCal respectively.
1 parent a35e0fc commit 828a75d

File tree

1 file changed

+89
-30
lines changed

1 file changed

+89
-30
lines changed

Recon/src/Recon/ParticleFlow.cxx

Lines changed: 89 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ void ParticleFlow::configure(framework::config::Parameters& ps) {
2525

2626
// Algorithm configuration
2727
singleParticle_ = ps.getParameter<bool>("singleParticle");
28+
tkHadCaloMatchDist_ = ps.getParameter<double>("tkHadCaloMatchDist");
29+
tkHadCaloMinEnergyRatio_ = ps.getParameter<double>("tkHadCaloMinEnergyRatio");
30+
tkHadCaloMaxEnergyRatio_ = ps.getParameter<double>("tkHadCaloMaxEnergyRatio");
2831

2932
// Calibration factors, from jason, temperary
3033
std::vector<float> em1{250.0, 750.0, 1250.0, 1750.0, 2250.0, 2750.0,
@@ -209,21 +212,43 @@ void ParticleFlow::produce(framework::Event& event) {
209212
}
210213
}
211214

212-
// NOT YET IMPLEMENTED...
213-
// tk-hadcalo linking (Side HCal)
215+
// tk-hadcalo linking (Side HCal) BY TILLRUE
214216
std::map<int, std::vector<int> > tkHadCaloMap;
215-
// for(int i=0; i<tracks.size(); i++){
216-
// const auto& tk = tracks[i];
217-
// for(int j=0; j<hcalClusters.size(); j++){
218-
// const auto& hcal = hcalClusters[j];
219-
// // TODO: add the matching logic here...
220-
// bool isMatch = true;
221-
// if(isMatch){
222-
// if (tkHadCaloMap.count(i)) tkHadCaloMap[i].push_back(j);
223-
// else tkHadCaloMap[i] = {j};
224-
// }
225-
// }
226-
// }
217+
std::map<int, std::vector<int> > HadCaloTkMap;
218+
std::map<std::pair<int, int>, float> tkHadCaloDist;
219+
for(int i=0; i<tracks.size(); i++){
220+
const auto& tk = tracks[i];
221+
const std::vector<float> xyz = tk.getPosition();
222+
const std::vector<double> pxyz = tk.getMomentum();
223+
const float p = sqrt(pow(pxyz[0], 2) + pow(pxyz[1], 2) + pow(pxyz[2], 2));
224+
225+
for(int j=0; j<hcalClusters.size(); j++){
226+
const auto& hcal = hcalClusters[j];
227+
// Matching logic same as for track ecalCluster matching
228+
const float hcalClusZ = hcal.getCentroidZ();
229+
const float tkXAtClus =
230+
xyz[0] + pxyz[0] / pxyz[2] * (hcalClusZ - xyz[2]); // extrapolation
231+
const float tkYAtClus =
232+
xyz[1] + pxyz[1] / pxyz[2] * (hcalClusZ - xyz[2]);
233+
float dist = hypot(
234+
(tkXAtClus - hcal.getCentroidX()) / std::max(1.0, hcal.getRMSX()),
235+
(tkYAtClus - hcal.getCentroidY()) / std::max(1.0, hcal.getRMSY()));
236+
tkHadCaloDist[{i, j}] = dist;
237+
bool isMatch =
238+
(dist < tkHadCaloMatchDist_) && (hcal.getEnergy() > tkHadCaloMinEnergyRatio_ * p &&
239+
hcal.getEnergy() < tkHadCaloMaxEnergyRatio_ * p); // matching criteria, need to be configured
240+
if (isMatch) {
241+
if (tkHadCaloMap.count(i))
242+
tkHadCaloMap[i].push_back(j);
243+
else
244+
tkHadCaloMap[i] = {j};
245+
if (HadCaloTkMap.count(j))
246+
HadCaloTkMap[j].push_back(i);
247+
else
248+
HadCaloTkMap[j] = {i};
249+
}
250+
}
251+
}
227252

228253
//
229254
// track / ecal cluster arbitration
@@ -245,7 +270,7 @@ void ParticleFlow::produce(framework::Event& event) {
245270
}
246271
}
247272

248-
// track / hcal cluster arbitration
273+
// ecal / hcal cluster arbitration
249274
std::vector<bool> EMIsHadLinked(ecalClusters.size(), false);
250275
std::vector<bool> HadIsEMLinked(hcalClusters.size(), false);
251276
std::map<int, int> EMHadPairs{};
@@ -263,6 +288,26 @@ void ParticleFlow::produce(framework::Event& event) {
263288
}
264289
}
265290

291+
//
292+
// track / hcal cluster arbitration BY TILLRUE
293+
//
294+
std::vector<bool> tkIsHadLinked(tracks.size(), false);
295+
std::vector<bool> HadIsTkLinked(hcalClusters.size(), false);
296+
std::map<int, int> tkHadPairs{};
297+
for (int i = 0; i < tracks.size(); i++) {
298+
if (tkHadCaloMap.count(i)) {
299+
// pick first (highest-energy) unused matching cluster
300+
for (int had_idx : tkHadCaloMap[i]) {
301+
if (!HadIsTkLinked[had_idx]) {
302+
HadIsTkLinked[had_idx] = true;
303+
tkIsHadLinked[i] = true;
304+
tkHadPairs[i] = had_idx;
305+
break;
306+
}
307+
}
308+
}
309+
}
310+
266311
// can consider combining satellite clusters here...
267312
// define some "primary cluster" ID criterion
268313
// and can add fails to the primaries
@@ -271,44 +316,58 @@ void ParticleFlow::produce(framework::Event& event) {
271316
// Begin building pf candidates from tracks
272317
//
273318

274-
// std::vector<ldmx::PFCandidate> chargedMatch;
275-
// std::vector<ldmx::PFCandidate> chargedUnmatch;
319+
// starting from tracks
276320
for (int i = 0; i < tracks.size(); i++) {
277321
ldmx::PFCandidate cand;
278322
fillCandTrack(cand, tracks[i]); // append track info to candidate
279-
280-
if (!tkIsEMLinked[i]) {
281-
// chargedUnmatch.push_back(cand);
282-
} else { // if track is linked with ECal cluster
323+
if (tkIsEMLinked[i]){ // if track is linked with ECal cluster
283324
fillCandEMCalo(cand, ecalClusters[tkEMPairs[i]]);
284-
if (EMIsHadLinked[tkEMPairs[i]]) { // if ECal is linked with HCal
285-
// cluster
286-
fillCandHadCalo(cand, hcalClusters[EMHadPairs[tkEMPairs[i]]]);
325+
if (EMIsHadLinked[tkEMPairs[i]]) { // if ECal is linked with HCal cluster
326+
if (!tkIsHadLinked[i]){ // if track is NOT also linked with Hcal
327+
fillCandHadCalo(cand, hcalClusters[EMHadPairs[tkEMPairs[i]]]);}
328+
}
329+
}
330+
331+
if(tkIsHadLinked[i]){ // if track is linked with Hcal
332+
fillCandHadCalo(cand, hcalClusters[tkHadPairs[i]]);
333+
if(HadIsEMLinked[tkHadPairs[i]]){ // if hcal is linked with ecal
334+
if(!tkIsEMLinked[i]){ // if ecal is NOT also linked with track
335+
fillCandEMCalo(cand,ecalClusters[HadEMPairs[tkHadPairs[i]]]);
336+
}
337+
} else if(!tkIsEMLinked[i]){
338+
cand.setDistTkHcalMatch(tkHadCaloDist[{i,tkHadPairs[i]}]);
339+
if(hcalClusters.size() > 1){
340+
cand.setHcalSecondEnergy(hcalClusters[tkHadPairs[i]+1].getEnergy());
341+
cand.setDistTkHcalSecondCluster(tkHadCaloDist[{i,tkHadPairs[i]+1}]);
342+
}
287343
}
288-
// chargedMatch.push_back(cand);
289344
}
290345
pfCands.push_back(cand);
291346
}
292347

293348
// std::vector<ldmx::PFCandidate> emMatch;
294349
// std::vector<ldmx::PFCandidate> emUnmatch;
350+
// ECal clusters
295351
for (int i = 0; i < ecalClusters.size(); i++) {
296-
// already linked with ECal in the previous step
297-
if (EMIsTkLinked[i]) continue;
352+
if (EMIsTkLinked[i]) continue; // already linked with ECal with Track in the previous step
353+
if (EMIsHadLinked[i] && HadIsTkLinked[EMHadPairs[i]]) continue; // already linked with track through Hcal
298354

299355
ldmx::PFCandidate cand;
300356
fillCandEMCalo(cand, ecalClusters[i]);
301-
if (EMIsHadLinked[tkEMPairs[i]]) {
357+
if (EMIsHadLinked[i]) { // is Ecal is linked with Hcal
302358
fillCandHadCalo(cand, hcalClusters[EMHadPairs[i]]);
303359
// emMatch.push_back(cand);
304360
} else {
305361
// emUnmatch.push_back(cand);
306362
}
307363
pfCands.push_back(cand);
308364
}
309-
std::vector<ldmx::PFCandidate> hadOnly;
365+
366+
// std::vector<ldmx::PFCandidate> hadOnly;
367+
// HCal clusters
310368
for (int i = 0; i < hcalClusters.size(); i++) {
311-
if (HadIsEMLinked[i]) continue;
369+
if (HadIsEMLinked[i]) continue; // already linked with ecal
370+
if (HadIsTkLinked[i]) continue; // already linked with track
312371
ldmx::PFCandidate cand;
313372
fillCandHadCalo(cand, hcalClusters[i]);
314373
// hadOnly.push_back(cand);

0 commit comments

Comments
 (0)