@@ -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