1 package org.hps.recon.particle;
2
3 import hep.physics.vec.BasicHep3Vector;
4 import hep.physics.vec.BasicHepLorentzVector;
5 import hep.physics.vec.Hep3Vector;
6 import hep.physics.vec.HepLorentzVector;
7 import hep.physics.vec.VecOp;
8
9 import java.util.ArrayList;
10 import java.util.HashMap;
11 import java.util.HashSet;
12 import java.util.List;
13 import java.util.Set;
14
15
16 import org.hps.conditions.beam.BeamEnergy.BeamEnergyCollection;
17 import org.hps.recon.ecal.cluster.ClusterUtilities;
18 import org.hps.recon.tracking.CoordinateTransformations;
19 import org.hps.recon.tracking.TrackUtils;
20 import org.hps.recon.utils.TrackClusterMatcher;
21 import org.hps.record.StandardCuts;
22 import org.lcsim.event.Cluster;
23 import org.lcsim.event.EventHeader;
24 import org.lcsim.event.ReconstructedParticle;
25 import org.lcsim.event.RelationalTable;
26 import org.lcsim.event.Track;
27 import org.lcsim.event.Vertex;
28 import org.lcsim.event.base.BaseCluster;
29 import org.lcsim.event.base.BaseReconstructedParticle;
30 import org.lcsim.geometry.Detector;
31 import org.lcsim.geometry.subdetector.HPSEcal3;
32 import org.lcsim.util.Driver;
33
34
35
36
37
38
39
40 public abstract class ReconParticleDriver extends Driver {
41
42
43
44
45 TrackClusterMatcher matcher = new TrackClusterMatcher();
46
47 String[] trackCollectionNames = {"GBLTracks"};
48
49 public static final int ELECTRON = 0;
50 public static final int POSITRON = 1;
51 public static final int MOLLER_TOP = 0;
52 public static final int MOLLER_BOT = 1;
53
54
55 private double MAXNSIGMAPOSITIONMATCH=15.0;
56
57 HPSEcal3 ecal;
58
59 protected boolean isMC = false;
60 private boolean disablePID = false;
61 protected StandardCuts cuts = new StandardCuts();
62 RelationalTable hitToRotated = null;
63 RelationalTable hitToStrips = null;
64
65 protected boolean enableTrackClusterMatchPlots = false;
66
67 public void setTrackClusterMatchPlots(boolean input) {
68 enableTrackClusterMatchPlots = input;
69 }
70
71
72 public void setUseCorrectedClusterPositionsForMatching(boolean val){
73 useCorrectedClusterPositionsForMatching = val;
74 }
75
76 boolean useCorrectedClusterPositionsForMatching = false;
77
78
79
80
81
82
83
84
85 protected boolean debug = false;
86
87
88
89
90 public boolean isMonteCarlo = false;
91
92
93
94
95 private final String simpleName = getClass().getSimpleName();
96
97
98
99
100
101 private List<ReconstructedParticle> electrons;
102
103
104
105 private List<ReconstructedParticle> positrons;
106
107
108
109 protected List<ReconstructedParticle> finalStateParticles;
110
111
112
113 protected List<ReconstructedParticle> unconstrainedV0Candidates;
114
115
116
117 protected List<ReconstructedParticle> beamConV0Candidates;
118
119
120
121 protected List<ReconstructedParticle> targetConV0Candidates;
122
123
124
125 protected List<Vertex> unconstrainedV0Vertices;
126
127
128
129 protected List<Vertex> beamConV0Vertices;
130
131
132
133 protected List<Vertex> targetConV0Vertices;
134
135
136
137
138
139 private String ecalClustersCollectionName = "EcalClusters";
140
141
142
143 private String trackCollectionName = "MatchedTracks";
144
145
146
147 private String finalStateParticlesColName = "FinalStateParticles";
148 private String OtherElectronsColName = "OtherElectrons";
149
150
151
152 protected String unconstrainedV0CandidatesColName = null;
153
154
155
156 protected String beamConV0CandidatesColName = null;
157
158
159
160 protected String targetConV0CandidatesColName = null;
161
162
163
164 protected String unconstrainedV0VerticesColName = null;
165
166
167
168 protected String beamConV0VerticesColName = null;
169
170
171
172 protected String targetConV0VerticesColName = null;
173
174
175
176
177 protected double[] beamSize = {0.001, 0.130, 0.050};
178
179
180
181
182 protected double[] beamPosition = {0.0, 0.0, 0.0};
183 protected double bField;
184 protected double beamEnergy = 1.056;
185
186
187
188
189
190
191
192 private int flipSign = 1;
193
194
195
196
197
198
199
200 public void setIsMC(boolean state) {
201 isMC = state;
202 }
203
204
205
206
207
208
209 public void setBeamConV0CandidatesColName(String beamConV0CandidatesColName) {
210 this.beamConV0CandidatesColName = beamConV0CandidatesColName;
211 }
212
213
214
215
216
217
218 public void setBeamConV0VerticesColName(String beamConV0VerticesColName) {
219 this.beamConV0VerticesColName = beamConV0VerticesColName;
220 }
221
222
223
224
225
226
227 public void setBeamPositionX(double X) {
228 beamPosition[1] = X;
229 }
230
231
232
233
234
235
236 public void setBeamSigmaX(double sigmaX) {
237 beamSize[1] = sigmaX;
238 }
239
240
241
242
243
244
245 public void setBeamPositionY(double Y) {
246 beamPosition[2] = Y;
247 }
248
249
250
251
252
253
254 public void setBeamSigmaY(double sigmaY) {
255 beamSize[2] = sigmaY;
256 }
257
258
259
260
261
262
263 public void setBeamPositionZ(double Z) {
264 beamPosition[0] = Z;
265 }
266
267
268
269
270
271
272
273
274 public void setDebug(boolean debug) {
275 this.debug = debug;
276 }
277
278
279
280
281
282
283 public void setEcalClusterCollectionName(String ecalClustersCollectionName) {
284 this.ecalClustersCollectionName = ecalClustersCollectionName;
285 }
286
287
288
289
290
291
292 public void setFinalStateParticlesColName(String finalStateParticlesColName) {
293 this.finalStateParticlesColName = finalStateParticlesColName;
294 }
295
296
297
298
299
300
301 public void setTargetConV0CandidatesColName(String targetConV0CandidatesColName) {
302 this.targetConV0CandidatesColName = targetConV0CandidatesColName;
303 }
304
305 public void setOtherElectronsColName(String input) {
306 OtherElectronsColName = input;
307 }
308
309
310
311
312
313
314 public void setTargetConV0VerticesColName(String targetConV0VerticesColName) {
315 this.targetConV0VerticesColName = targetConV0VerticesColName;
316 }
317
318
319
320
321
322
323 public void setTrackCollectionName(String trackCollectionName) {
324 this.trackCollectionName = trackCollectionName;
325 }
326
327
328
329
330
331
332 public void setUnconstrainedV0CandidatesColName(String unconstrainedV0CandidatesColName) {
333 this.unconstrainedV0CandidatesColName = unconstrainedV0CandidatesColName;
334 }
335
336
337
338
339
340
341 public void setUnconstrainedV0VerticesColName(String unconstrainedV0VerticesColName) {
342 this.unconstrainedV0VerticesColName = unconstrainedV0VerticesColName;
343 }
344
345
346
347
348
349
350 public void setTrackCollectionNames(String[] trackCollectionNames) {
351 this.trackCollectionNames = trackCollectionNames;
352 }
353
354
355
356
357
358
359 public void setNSigmaPositionMatch(double nsigma) {
360 MAXNSIGMAPOSITIONMATCH = nsigma;
361 }
362
363
364 public void setDisablePID(boolean disablePID) {
365 this.disablePID = disablePID;
366 }
367
368
369
370
371 @Override
372 protected void detectorChanged(Detector detector) {
373 matcher.enablePlots(enableTrackClusterMatchPlots);
374
375
376 Hep3Vector ip = new BasicHep3Vector(0., 0., 500.0);
377 bField = detector.getFieldMap().getField(ip).y();
378 if (bField < 0) {
379 flipSign = -1;
380 }
381
382 ecal = (HPSEcal3) detector.getSubdetector("Ecal");
383 matcher.setBFieldMap(detector.getFieldMap());
384 BeamEnergyCollection beamEnergyCollection =
385 this.getConditionsManager().getCachedConditions(BeamEnergyCollection.class, "beam_energies").getCachedData();
386 beamEnergy = beamEnergyCollection.get(0).getBeamEnergy();
387 matcher.setBeamEnergy(beamEnergy);
388 cuts.changeBeamEnergy(beamEnergy);
389 }
390
391 public void setMaxMatchChisq(double input) {
392 cuts.setMaxMatchChisq(input);
393 }
394
395
396 public void setMaxElectronP(double input) {
397 cuts.setMaxElectronP(input);
398 }
399
400 public void setMaxMatchDt(double input) {
401 cuts.setMaxMatchDt(input);
402 }
403
404 public void setTrackClusterTimeOffset(double input) {
405 cuts.setTrackClusterTimeOffset(input);
406 }
407
408 protected abstract List<ReconstructedParticle> particleCuts(List<ReconstructedParticle> finalStateParticles);
409
410
411
412
413
414
415
416
417
418
419 protected abstract void findVertices(List<ReconstructedParticle> electrons, List<ReconstructedParticle> positrons);
420
421
422
423
424
425
426
427
428
429
430
431 protected List<ReconstructedParticle> makeReconstructedParticles(List<Cluster> clusters,
432 List<List<Track>> trackCollections) {
433
434
435 List<ReconstructedParticle> particles = new ArrayList<ReconstructedParticle>();
436
437
438
439 Set<Cluster> unmatchedClusters = new HashSet<Cluster>(clusters);
440
441
442 HashMap<Cluster, Track> clusterToTrack = new HashMap<Cluster, Track>();
443
444
445
446
447
448
449 for (List<Track> tracks : trackCollections) {
450
451 for (Track track : tracks) {
452
453
454 ReconstructedParticle particle = new BaseReconstructedParticle();
455
456
457 particle.addTrack(track);
458
459
460
461
462 ((BaseReconstructedParticle) particle).setType(track.getType());
463
464
465 int charge = (int) Math.signum(track.getTrackStates().get(0).getOmega());
466 ((BaseReconstructedParticle) particle).setCharge(charge * flipSign);
467
468
469 ((BaseReconstructedParticle) particle).setGoodnessOfPid(9999);
470
471
472
473
474 if (particle.getCharge() > 0) {
475 ((BaseReconstructedParticle) particle).setParticleIdUsed(new SimpleParticleID(-11, 0, 0, 0));
476 } else if (particle.getCharge() < 0) {
477 ((BaseReconstructedParticle) particle).setParticleIdUsed(new SimpleParticleID(11, 0, 0, 0));
478 }
479
480
481 double smallestNSigma = Double.MAX_VALUE;
482
483
484 Cluster matchedCluster = null;
485 for (Cluster cluster : clusters) {
486 double clusTime = ClusterUtilities.getSeedHitTime(cluster);
487 double trkT = TrackUtils.getTrackTime(track, hitToStrips, hitToRotated);
488
489 if (Math.abs(clusTime - trkT - cuts.getTrackClusterTimeOffset()) > cuts.getMaxMatchDt()){
490 if (debug) {
491 System.out.println("Failed cluster-track deltaT!");
492 System.out.println(clusTime + " " + trkT + " " + cuts.getTrackClusterTimeOffset() + ">" + cuts.getMaxMatchDt());
493 }
494 continue;
495 }
496
497
498
499
500 Cluster originalCluster = cluster;
501 if(useCorrectedClusterPositionsForMatching){
502 cluster = new BaseCluster(cluster);
503 double ypos = TrackUtils.getTrackStateAtECal(particle.getTracks().get(0)).getReferencePoint()[2];
504 ClusterUtilities.applyCorrections(ecal, cluster, ypos,isMC);
505 }
506
507
508 final double thisNSigma = matcher.getNSigmaPosition(cluster, particle);
509 if (enableTrackClusterMatchPlots) {
510 if (TrackUtils.getTrackStateAtECal(track) != null)
511 matcher.isMatch(cluster, track);
512 }
513
514
515 if (thisNSigma > MAXNSIGMAPOSITIONMATCH){
516 if (debug) {
517 System.out.println("Failed cluster-track NSigma Cut!");
518 System.out.println("match NSigma = "+thisNSigma + "; Max NSigma = " + MAXNSIGMAPOSITIONMATCH );
519 }
520 continue;
521 }
522
523
524
525 if (thisNSigma > smallestNSigma) {
526 if (debug) {
527 System.out.println("Already found a better match than this!");
528 System.out.println("match NSigma = "+thisNSigma + "; smallest NSigma = " + smallestNSigma );
529 }
530 continue;
531 }
532
533 smallestNSigma = thisNSigma;
534 matchedCluster = originalCluster;
535
536
537 if (track.getType() >= 32 || !clusterToTrack.containsKey(matchedCluster)) {
538 clusterToTrack.put(matchedCluster, track);
539 }
540 }
541
542
543 if (matchedCluster != null) {
544
545
546 particle.addCluster(matchedCluster);
547
548
549 ((BaseReconstructedParticle) particle).setGoodnessOfPid(smallestNSigma);
550
551
552 final int pid = particle.getParticleIDUsed().getPDG();
553 if (Math.abs(pid) == 11) {
554 if (!disablePID)
555 ((BaseCluster) matchedCluster).setParticleId(pid);
556 }
557
558
559 unmatchedClusters.remove(matchedCluster);
560 }
561
562
563 particles.add(particle);
564 }
565 }
566
567
568 for (Cluster unmatchedCluster : unmatchedClusters) {
569
570
571 ReconstructedParticle particle = new BaseReconstructedParticle();
572
573
574 ((BaseReconstructedParticle) particle).setParticleIdUsed(new SimpleParticleID(22, 0, 0, 0));
575
576 int pid = particle.getParticleIDUsed().getPDG();
577 if (Math.abs(pid) != 11) {
578 if (!disablePID)
579 ((BaseCluster) unmatchedCluster).setParticleId(pid);
580 }
581
582
583 particle.addCluster(unmatchedCluster);
584
585
586 ((BaseReconstructedParticle) particle).setCharge(0);
587
588
589 particles.add(particle);
590 }
591
592
593 for (Cluster cluster : clusters) {
594 if (cluster.getParticleId() != 0) {
595 if (clusterToTrack.containsKey(cluster)) {
596 Track matchedT = clusterToTrack.get(cluster);
597 double ypos = TrackUtils.getTrackStateAtECal(matchedT).getReferencePoint()[2];
598 ClusterUtilities.applyCorrections(ecal, cluster, ypos, isMC);
599 } else {
600 ClusterUtilities.applyCorrections(ecal, cluster, isMC);
601 }
602 }
603 }
604
605 for (ReconstructedParticle particle : particles) {
606 double clusterEnergy = 0;
607 Hep3Vector momentum = null;
608
609 if (!particle.getClusters().isEmpty()) {
610 clusterEnergy = particle.getClusters().get(0).getEnergy();
611 }
612
613 if (!particle.getTracks().isEmpty()) {
614 momentum = new BasicHep3Vector(particle.getTracks().get(0).getTrackStates().get(0).getMomentum());
615 momentum = CoordinateTransformations.transformVectorToDetector(momentum);
616 } else if (!particle.getClusters().isEmpty()) {
617 momentum = new BasicHep3Vector(particle.getClusters().get(0).getPosition());
618 momentum = VecOp.mult(clusterEnergy, VecOp.unit(momentum));
619 }
620 HepLorentzVector fourVector = new BasicHepLorentzVector(clusterEnergy, momentum);
621 ((BaseReconstructedParticle) particle).set4Vector(fourVector);
622
623
624
625 if(!particle.getClusters().isEmpty() && useCorrectedClusterPositionsForMatching){
626 double goodnessPID_corrected = matcher.getNSigmaPosition(particle.getClusters().get(0), particle);
627 ((BaseReconstructedParticle) particle).setGoodnessOfPid(goodnessPID_corrected);
628 }
629
630 }
631
632
633 return particles;
634 }
635
636
637
638
639
640
641
642 protected void printDebug(String debugMessage) {
643
644 if (debug) {
645 System.out.printf("%s :: %s%n", simpleName, debugMessage);
646 }
647 }
648
649
650
651
652
653
654
655 @Override
656 protected void process(EventHeader event) {
657
658
659
660 if (!event.hasCollection(Cluster.class, ecalClustersCollectionName)) {
661 return;
662 }
663
664
665 printDebug("\nProcessing Event...");
666
667
668 List<Cluster> clusters = event.get(Cluster.class, ecalClustersCollectionName);
669
670
671 printDebug("Clusters :: " + clusters.size());
672
673
674
675
676
677
678
679
680 List<List<Track>> trackCollections = new ArrayList<List<Track>>();
681 if (trackCollectionNames != null) {
682 for (String collectionName : trackCollectionNames) {
683 if (event.hasCollection(Track.class, collectionName)) {
684
685 printDebug("Tracks :: " + event.get(Track.class, collectionName).size());
686 trackCollections.add(event.get(Track.class, collectionName));
687 }
688 }
689 } else {
690 if (event.hasCollection(Track.class)) {
691 trackCollections = event.get(Track.class);
692 } else {
693 trackCollections.add(new ArrayList<Track>(0));
694 }
695 }
696
697 hitToRotated = TrackUtils.getHitToRotatedTable(event);
698 hitToStrips = TrackUtils.getHitToStripsTable(event);
699
700
701
702 finalStateParticles = new ArrayList<ReconstructedParticle>();
703 electrons = new ArrayList<ReconstructedParticle>();
704 positrons = new ArrayList<ReconstructedParticle>();
705 unconstrainedV0Candidates = new ArrayList<ReconstructedParticle>();
706 beamConV0Candidates = new ArrayList<ReconstructedParticle>();
707 targetConV0Candidates = new ArrayList<ReconstructedParticle>();
708 unconstrainedV0Vertices = new ArrayList<Vertex>();
709 beamConV0Vertices = new ArrayList<Vertex>();
710 targetConV0Vertices = new ArrayList<Vertex>();
711
712
713
714 finalStateParticles.addAll(makeReconstructedParticles(clusters, trackCollections));
715
716
717
718 for (ReconstructedParticle finalStateParticle : finalStateParticles) {
719
720 if (finalStateParticle.getCharge() > 0) {
721 positrons.add(finalStateParticle);
722 }
723 else if (finalStateParticle.getCharge() < 0) {
724 electrons.add(finalStateParticle);
725 }
726 }
727
728
729
730 printDebug("Number of Electrons: " + electrons.size());
731 printDebug("Number of Positrons: " + positrons.size());
732
733
734
735 findVertices(electrons, positrons);
736
737 List<ReconstructedParticle> goodFinalStateParticles = particleCuts(finalStateParticles);
738
739 printDebug("Final State Particles :: " + goodFinalStateParticles.size());
740
741 event.put(finalStateParticlesColName, goodFinalStateParticles, ReconstructedParticle.class, 0);
742 for (ReconstructedParticle ele : goodFinalStateParticles) {
743 if (electrons.contains(ele))
744 electrons.remove(ele);
745 }
746 event.put(OtherElectronsColName, electrons, ReconstructedParticle.class, 0);
747
748
749
750
751 if (unconstrainedV0CandidatesColName != null) {
752 printDebug("Unconstrained V0 Candidates: " + unconstrainedV0Candidates.size());
753 event.put(unconstrainedV0CandidatesColName, unconstrainedV0Candidates, ReconstructedParticle.class, 0);
754 }
755 if (beamConV0CandidatesColName != null) {
756 printDebug("Beam-Constrained V0 Candidates: " + beamConV0Candidates.size());
757 event.put(beamConV0CandidatesColName, beamConV0Candidates, ReconstructedParticle.class, 0);
758 }
759 if (targetConV0CandidatesColName != null) {
760 printDebug("Target-Constrained V0 Candidates: " + targetConV0Candidates.size());
761 event.put(targetConV0CandidatesColName, targetConV0Candidates, ReconstructedParticle.class, 0);
762 }
763 if (unconstrainedV0VerticesColName != null) {
764 printDebug("Unconstrained V0 Vertices: " + unconstrainedV0Vertices.size());
765 event.put(unconstrainedV0VerticesColName, unconstrainedV0Vertices, Vertex.class, 0);
766 }
767 if (beamConV0VerticesColName != null) {
768 printDebug("Beam-Constrained V0 Vertices: " + beamConV0Vertices.size());
769 event.put(beamConV0VerticesColName, beamConV0Vertices, Vertex.class, 0);
770 }
771 if (targetConV0VerticesColName != null) {
772 printDebug("Target-Constrained V0 Vertices: " + targetConV0Vertices.size());
773 event.put(targetConV0VerticesColName, targetConV0Vertices, Vertex.class, 0);
774 }
775 }
776
777
778
779
780 @Override
781 protected void startOfData() {
782
783 if (ecalClustersCollectionName == null) {
784 ecalClustersCollectionName = "EcalClusters";
785 }
786 if (trackCollectionName == null) {
787 trackCollectionName = "GBLTracks";
788 }
789 if (finalStateParticlesColName == null) {
790 finalStateParticlesColName = "FinalStateParticles";
791 }
792 if (unconstrainedV0CandidatesColName == null) {
793 unconstrainedV0CandidatesColName = "UnconstrainedV0Candidates";
794 }
795 if (beamConV0CandidatesColName == null) {
796 beamConV0CandidatesColName = "BeamspotConstrainedV0Candidates";
797 }
798 if (targetConV0CandidatesColName == null) {
799 targetConV0CandidatesColName = "TargetConstrainedV0Candidates";
800 }
801 if (unconstrainedV0VerticesColName == null) {
802 unconstrainedV0VerticesColName = "UnconstrainedV0Vertices";
803 }
804 if (beamConV0VerticesColName == null) {
805 beamConV0VerticesColName = "BeamspotConstrainedV0Vertices";
806 }
807 if (targetConV0VerticesColName == null) {
808 targetConV0VerticesColName = "TargetConstrainedV0Vertices";
809 }
810 }
811
812 @Override
813 protected void endOfData() {
814 if (enableTrackClusterMatchPlots)
815 matcher.saveHistograms();
816 }
817
818
819 public void setSnapToEdge(boolean val){
820 this.matcher.setSnapToEdge(val);
821 }
822 }