lcsim/src/org/lcsim/contrib/uiowa/template
diff -u -r1.6 -r1.7
--- NonTrivialPFA.java 18 Jul 2006 00:45:05 -0000 1.6
+++ NonTrivialPFA.java 18 Aug 2006 00:13:55 -0000 1.7
@@ -4,6 +4,7 @@
import hep.physics.vec.*;
import org.lcsim.util.*;
+import org.lcsim.util.decision.*;
import org.lcsim.util.hitmap.*;
import org.lcsim.event.*;
import org.lcsim.event.util.*;
@@ -20,7 +21,10 @@
import org.lcsim.mc.fast.tracking.MCFastTracking;
import org.lcsim.recon.pfa.identifier.SimpleNeutralParticleMaker;
import org.lcsim.recon.pfa.identifier.SimpleChargedParticleMaker;
-//import org.lcsim.recon.pfa.identifier.DebugChargedParticleMaker;
+import org.lcsim.recon.pfa.identifier.MIPChargedParticleMaker;
+import org.lcsim.recon.pfa.identifier.SimpleTrackClusterMatcher;
+import org.lcsim.recon.pfa.identifier.SimpleTrackMIPClusterMatcher;
+import org.lcsim.recon.pfa.identifier.TrackClusterMatcher;
import org.lcsim.recon.cluster.util.BothCalorimetersDecision;
import org.lcsim.recon.cluster.util.ClusterListFilterDriver;
import org.lcsim.recon.cluster.util.VetoClustersFromParticles;
@@ -32,6 +36,7 @@
import org.lcsim.util.decision.ParticlePDGDecision;
import org.lcsim.recon.cluster.cheat.PerfectClusterer;
import org.lcsim.recon.cluster.structural.ChargedNeutralFragmentSeparator;
+import org.lcsim.recon.cluster.util.ClusterFirstLayerDecision;
import org.lcsim.util.aida.AIDA;
@@ -45,6 +50,7 @@
// Book-keeping
HitBookKeeper accountant = new HitBookKeeper();
accountant.setDebug(false);
+ //accountant.setDebug(true);
// Set up the MC list
//
@@ -68,52 +74,149 @@
add( new SimCalorimeterHitsDriver() );
// Step 1: Set up input hit lists:
- HitListToHitMapDriver hitmapEcal = new HitListToHitMapDriver();
- hitmapEcal.addInputList("EcalBarrDigiHits");
- hitmapEcal.addInputList("EcalEndcapDigiHits");
- hitmapEcal.setOutput("input hit map ecal");
- HitListToHitMapDriver hitmapHcal = new HitListToHitMapDriver();
- hitmapHcal.addInputList("HcalBarrDigiHits");
- hitmapHcal.addInputList("HcalEndcapDigiHits");
- hitmapHcal.setOutput("input hit map hcal");
- add(hitmapEcal);
- add(hitmapHcal);
+ {
+ HitListToHitMapDriver hitmapEcal = new HitListToHitMapDriver();
+ hitmapEcal.addInputList("EcalBarrDigiHits");
+ hitmapEcal.addInputList("EcalEndcapDigiHits");
+ hitmapEcal.setOutput("input hit map ecal");
+ HitListToHitMapDriver hitmapHcal = new HitListToHitMapDriver();
+ hitmapHcal.addInputList("HcalBarrDigiHits");
+ hitmapHcal.addInputList("HcalEndcapDigiHits");
+ hitmapHcal.setOutput("input hit map hcal");
+ add(hitmapEcal);
+ add(hitmapHcal);
+ }
accountant.addListOfNamedLists( new String[] { "input hit map ecal", "input hit map hcal" } );
// Find tracks
- // Output: List<Track> saved as EventHeader.TRACKS
+ // Non-cheating: Output: List<Track> saved as EventHeader.TRACKS
add (new MCFastTracking());
+ // Cheating: Output: CombinedTracks (type CheatTrack)
+ org.lcsim.recon.ztracking.cheater.TrackingCheater trackCheater = new org.lcsim.recon.ztracking.cheater.TrackingCheater();
+ trackCheater.setUseFinalStateParticles(true);
+ add(trackCheater);
+
+ String nonCheatingTrackList = EventHeader.TRACKS;
+ String cheatingTrackList = new String("CombinedTracks");
+ //String trackList = nonCheatingTrackList;
+ String trackList = cheatingTrackList;
+
+
+ // Finding photons and MIPs needs to be done carefully, since
+ // many photons look like MIPs and vice-versa.
+ // For now we do it in chunks.
+
+ // Find MIP candidates in ECAL, starting near the front:
+ {
+ TrackClusterDriver ecalFrontSideMIPs = new TrackClusterDriver("input hit map ecal", "front-side mips ecal", "hit map ecal without front-side mips");
+ ecalFrontSideMIPs.filterOutputClusters(new ClusterFirstLayerDecision(4));
+ add(ecalFrontSideMIPs);
+ }
+
+ // Check if they match a track (ugly... don't need to make the particles!)
+ {
+ MIPChargedParticleMaker mipHadID = new MIPChargedParticleMaker();
+ SimpleTrackMIPClusterMatcher mipMatch = new SimpleTrackMIPClusterMatcher();
+ add(mipMatch);
+ mipHadID.setTrackMatcher(mipMatch);
+ mipHadID.setInputTrackList(trackList);
+ mipHadID.setOutputTrackList("tracks left over from front-side mips");
+ mipHadID.setInputMIPList("front-side mips ecal");
+ mipHadID.setOutputMIPList("mips minus front-side mips ecal");
+ mipHadID.setOutputParticleList("front-side mip particles");
+ add(mipHadID);
+ }
+
+ // Isolate the genuine (charged) MIPs from the rest
+ {
+ ClusterListFilterDriver filterRemoveChargedMIPs = new ClusterListFilterDriver();
+ ClusterListFilterDriver filterSelectChargedMIPs = new ClusterListFilterDriver();
+ VetoClustersFromParticles vetoChargedMIPs = new VetoClustersFromParticles("front-side mip particles"); // veto MIPs
+ DecisionMakerSingle<Cluster> selectChargedMIPs = new NotDecisionMakerSingle<Cluster> (vetoChargedMIPs); // invert veto to select MIPs
+ filterRemoveChargedMIPs.setInputDecision(vetoChargedMIPs);
+ filterSelectChargedMIPs.setInputDecision(selectChargedMIPs);
+ filterRemoveChargedMIPs.setInputList("front-side mips ecal");
+ filterSelectChargedMIPs.setInputList("front-side mips ecal");
+ filterRemoveChargedMIPs.setOutputList("neutral front-side mips ecal");
+ filterSelectChargedMIPs.setOutputList("charged front-side mips ecal");
+ add(vetoChargedMIPs);
+ add(filterRemoveChargedMIPs);
+ add(filterSelectChargedMIPs);
+ }
+ // Merge the non-charged "MIP" hits back in
+ {
+ ClusterListToHitMapDriver convertFakeMIPsToHitMap = new ClusterListToHitMapDriver("neutral front-side mips ecal", "hit map ecal of neutral front-side mips");
+ add(convertFakeMIPsToHitMap);
+ HitMapAddDriver addFakeMIPHitsBack = new HitMapAddDriver();
+ addFakeMIPHitsBack.addInputHitMap("hit map ecal of neutral front-side mips");
+ addFakeMIPHitsBack.addInputHitMap("hit map ecal without front-side mips");
+ addFakeMIPHitsBack.setOutputHitMap("hit map ecal without charged front-side mips");
+ add(addFakeMIPHitsBack);
+ }
+
+ // Find photons
+ {
+ MSTPhotonFinderDriver photonFinder = new MSTPhotonFinderDriver();
+ photonFinder.setCoreThreshold(7.5);
+ photonFinder.setFragmentThreshold(7.5);
+ photonFinder.setLayerProximityThreshold(2);
+ photonFinder.setCoreSizeMinimum(10);
+ photonFinder.setFragmentSizeMaximum(6);
+ photonFinder.setInputHitMap("hit map ecal without charged front-side mips");
+ photonFinder.setOutputHitMap("hit map ecal without photons or charged front-side mips");
+ photonFinder.setOutputClusterList("photon clusters");
+ //photonFinder.setDebug(true);
+ add(photonFinder);
+ }
+ // Merge the charged MIP hits back in
+ {
+ ClusterListToHitMapDriver convertRealMIPsToHitMap = new ClusterListToHitMapDriver("charged front-side mips ecal", "hit map ecal of charged front-side mips");
+ add(convertRealMIPsToHitMap);
+ HitMapAddDriver addRealMIPHitsBack = new HitMapAddDriver();
+ addRealMIPHitsBack.addInputHitMap("hit map ecal of charged front-side mips");
+ addRealMIPHitsBack.addInputHitMap("hit map ecal without photons or charged front-side mips");
+ addRealMIPHitsBack.setOutputHitMap("hit map ecal without photons");
+ add(addRealMIPHitsBack);
+ }
+
// Find track segments in ECAL and HCAL
- TrackClusterDriver ecalMIP = new TrackClusterDriver("input hit map ecal", "mips ecal", "hit map ecal without mips");
- TrackClusterDriver hcalMIP = new TrackClusterDriver("input hit map hcal", "mips hcal", "hit map hcal without mips");
- add(ecalMIP);
- add(hcalMIP);
+ {
+ TrackClusterDriver ecalMIP = new TrackClusterDriver("hit map ecal without photons", "mips ecal", "hit map ecal without mips or photons");
+ TrackClusterDriver hcalMIP = new TrackClusterDriver("input hit map hcal", "mips hcal", "hit map hcal without mips");
+ add(ecalMIP);
+ add(hcalMIP);
+ }
// Merge the two lists:
- ListAddDriver<Cluster> mergeMIPs = new ListAddDriver<Cluster>();
- mergeMIPs.addInputList("mips ecal");
- mergeMIPs.addInputList("mips hcal");
- mergeMIPs.setOutputList("mips");
- add(mergeMIPs);
- accountant.addListOfNamedLists( new String[] { "hit map ecal without mips", "hit map hcal without mips", "mips ecal", "mips hcal" } );
- accountant.addListOfNamedLists( new String[] { "hit map ecal without mips", "hit map hcal without mips", "mips" } );
-
- // Find photons in the ECAL (cheat for now)
- add(new ListFilterDriver(new ParticlePDGDecision(22), mcListName, "MCParticles photons only"));
- PerfectClusterer myCheatPhotonFinder = new PerfectClusterer();
- myCheatPhotonFinder.setInputHitMap("hit map ecal without mips");
- myCheatPhotonFinder.setOutputHitMap("hit map ecal without mips or photons");
- myCheatPhotonFinder.setOutputClusterList("photon clusters");
- myCheatPhotonFinder.setMCParticleList("MCParticles photons only");
- myCheatPhotonFinder.allowHitSharing(false);
- add(myCheatPhotonFinder);
- accountant.addListOfNamedLists( new String[] { "hit map ecal without mips or photons", "hit map hcal without mips", "mips ecal", "mips hcal", "photon clusters" } );
- // ID them
- SimpleNeutralParticleMaker myPhotonIdentifier = new SimpleNeutralParticleMaker(22); // 22 = photon
- myPhotonIdentifier.setInputClusterList("photon clusters");
- myPhotonIdentifier.setOutputParticleList("photon particles");
- add(myPhotonIdentifier);
- accountant.addListOfNamedLists( new String[] { "hit map ecal without mips or photons", "hit map hcal without mips", "mips ecal", "mips hcal", "photon particles" } );
+ {
+ ListAddDriver<Cluster> mergeMIPs = new ListAddDriver<Cluster>();
+ mergeMIPs.addInputList("mips ecal");
+ mergeMIPs.addInputList("mips hcal");
+ mergeMIPs.setOutputList("mips");
+ add(mergeMIPs);
+ accountant.addListOfNamedLists( new String[] { "hit map ecal without mips or photons", "hit map hcal without mips", "mips ecal", "mips hcal", "photon clusters" } );
+ accountant.addListOfNamedLists( new String[] { "hit map ecal without mips or photons", "hit map hcal without mips", "mips", "photon clusters" } );
+ }
+
+ //// Find photons in the ECAL (cheat for now)
+ //add(new ListFilterDriver(new ParticlePDGDecision(22), mcListName, "MCParticles photons only"));
+ //PerfectClusterer myCheatPhotonFinder = new PerfectClusterer();
+ //myCheatPhotonFinder.setInputHitMap("hit map ecal without mips");
+ //myCheatPhotonFinder.setOutputHitMap("hit map ecal without mips or photons");
+ //myCheatPhotonFinder.setOutputClusterList("photon clusters");
+ //myCheatPhotonFinder.setMCParticleList("MCParticles photons only");
+ //myCheatPhotonFinder.allowHitSharing(false);
+ //add(myCheatPhotonFinder);
+ //accountant.addListOfNamedLists( new String[] { "hit map ecal without mips or photons", "hit map hcal without mips", "mips ecal", "mips hcal", "photon clusters" } );
+
+ // ID photons
+ {
+ SimpleNeutralParticleMaker myPhotonIdentifier = new SimpleNeutralParticleMaker(22); // 22 = photon
+ myPhotonIdentifier.setInputClusterList("photon clusters");
+ myPhotonIdentifier.setOutputParticleList("photon particles");
+ add(myPhotonIdentifier);
+ accountant.addListOfNamedLists( new String[] { "hit map ecal without mips or photons", "hit map hcal without mips", "mips ecal", "mips hcal", "photon particles" } );
+ }
// Find clumps in ECAL and HCAL
// Clumps are defined as contiguous sets of
@@ -201,6 +304,7 @@
Driver checkpoint = new LikelihoodEvaluatorCheckpointDriver(eval, 10);
add(checkpoint);
} else {
+
// Step 6a: Structural algorithm
// Inputs from event:
// * Big (MST) clusters
@@ -255,64 +359,62 @@
accountant.addListOfNamedLists( new String[] { "ecal hit map after mst", "hcal hit map after mst", "skeletons plus halo", "structural unused hits minus halo", "mst clusters linked (<10 hits)", "photon particles" } );
// Step 6c: Extrapolate tracks to ECAL surface, form charged particles
- // Inputs:
- // * The tracks (which we'll extrapolate)
- // * The MIPs (which are our best chance of a good association)
- // * The fleshed-out skeletons (to match the tracks to -- or to their MIP components -- and form particles)
- // Outputs:
- // * Any unused tracks
- // * The reconstructed particles
- SimpleChargedParticleMaker hadID = new SimpleChargedParticleMaker();
- hadID.setInputTrackList(EventHeader.TRACKS);
- hadID.setOutputTrackList("leftover tracks");
- hadID.setInputMIPList("mips");
- hadID.setInputClusterList("skeletons plus halo");
- hadID.setOutputParticleList("charged hadron particles");
- hadID.setDebug(false);
- add(hadID);
+
+ // First try the MIPs...
+ {
+ MIPChargedParticleMaker hadIDmip = new MIPChargedParticleMaker();
+ SimpleTrackMIPClusterMatcher mipMatch = new SimpleTrackMIPClusterMatcher();
+ add(mipMatch);
+ hadIDmip.setTrackMatcher(mipMatch);
+ hadIDmip.setInputTrackList(trackList);
+ hadIDmip.setOutputTrackList("tracks minus mip associations");
+ hadIDmip.setInputMIPList("mips");
+ hadIDmip.setOutputParticleList("charged hadron particles with mip association");
+ hadIDmip.setOutputMIPList("unmatched mips");
+ hadIDmip.addClusterList("skeletons plus halo", "skeletons plus halo minus charged particles from mips");
+ hadIDmip.addClusterList("mst clusters linked (<10 hits)", "mst clusters linked (<10 hits) minus charged particles from mips");
+ add(hadIDmip);
+ }
+
+ // Then try the clusters generically:
+ {
+ SimpleChargedParticleMaker hadID = new SimpleChargedParticleMaker();
+ SimpleTrackClusterMatcher clusMatch = new SimpleTrackClusterMatcher();
+ add(clusMatch);
+ hadID.setTrackMatcher(clusMatch);
+ hadID.setInputTrackList("tracks minus mip associations");
+ hadID.setOutputTrackList("leftover tracks");
+ hadID.setInputClusterList("skeletons plus halo minus charged particles from mips");
+ hadID.setOutputParticleList("charged hadron particles with non-mip association");
+ add(hadID);
+ }
+
+ // Merge the two particle lists:
+ {
+ ListAddDriver<ReconstructedParticle> mergeParticles = new ListAddDriver<ReconstructedParticle>();
+ mergeParticles.addInputList("charged hadron particles with mip association");
+ mergeParticles.addInputList("charged hadron particles with non-mip association");
+ mergeParticles.setOutputList("charged hadron particles");
+ add(mergeParticles);
+ }
// Step 6d: Handle fragments
- // Here are the fragment/small neutrals we've accumulated:
- // * Small clusters ("mst clusters linked (<10 hits)")
- // * Unassigned structural hits, if any ("structural unused hits minus halo")
- // Convert the individual hits into clusters:
- add(new HitMapToClusterListDriver("structural unused hits minus halo", "structural unused hits minus halo (clusters)"));
- // Merge fragments into a single cluster list:
- ListAddDriver combineFragmentClusters = new ListAddDriver();
- combineFragmentClusters.addInputList("mst clusters linked (<10 hits)");
- combineFragmentClusters.addInputList("structural unused hits minus halo (clusters)");
- combineFragmentClusters.setOutputList("small clusters");
- add(combineFragmentClusters);
-
- // Test: Try to figure out which are charged and which are neutral
- ChargedNeutralFragmentSeparator testCharged = new ChargedNeutralFragmentSeparator(EventHeader.TRACKS);
- testCharged.initPlots();
- add(testCharged);
- add(new ClusterListFilterDriver(testCharged, "small clusters", "charged small clusters"));
-
- // FragmentHandler
- // Inputs:
- // * Charged particles ("charged hadron particles")
- // * Skeleton clusters ("skeletons plus halo")
- // * Small clusters ("small clusters")
- // Outputs:
- // * Particles (one per merged cluster)
- // * Clusters after merging in fragments ("merged clusters");
- // * Any remaining unassigned hits("leftover hits after fragment merge")
+
org.lcsim.recon.cluster.structural.FragmentHandler fragMergeDriver = new org.lcsim.recon.cluster.structural.FragmentHandler();
fragMergeDriver.addInputClusterList("skeletons plus halo");
- fragMergeDriver.addInputClusterList("small clusters");
+ fragMergeDriver.addInputClusterList("mst clusters linked (<10 hits)");
fragMergeDriver.setOutputClusterList("clusters with fragments merged");
fragMergeDriver.setOutputHitMap("hits left over after fragment merge");
org.lcsim.recon.cluster.structural.SimpleFragmentIdentifier fragID = new org.lcsim.recon.cluster.structural.SimpleFragmentIdentifier(10, 100.0);
fragID.addParticleList("charged hadron particles");
fragMergeDriver.setFragmentIdentifier(fragID); // don't cheat
accountant.addListOfNamedLists( new String[] { "ecal hit map after mst", "hcal hit map after mst", "clusters with fragments merged", "hits left over after fragment merge", "photon particles" } );
+
// What if we want to cheat? Set it up...
{
// Here are our cluster lists:
- // "skeletons plus halo"
- // "mst clusters linked (<10 hits)"
+ // "skeletons plus halo plus orphan mips"
+ // "mst clusters linked (<10 hits) minus orphan mips"
// Here is the MC list:
// "GenFinalStateParticles" [or sim]
// Here are the output lists:
@@ -330,24 +432,56 @@
org.lcsim.recon.cluster.structural.CheatFragmentIdentifier cheatFragID = new org.lcsim.recon.cluster.structural.CheatFragmentIdentifier(hitListNames, clusterListNames, mcListName, "CheatFragmentIdentifier info P->C", "CheatFragmentIdentifier info C->P");
fragMergeDriver.setFragmentIdentifier(cheatFragID); // cheat
}
+
org.lcsim.recon.cluster.structural.SimpleFragmentMerger fragMerge = new org.lcsim.recon.cluster.structural.SimpleFragmentMerger();
fragMergeDriver.setFragmentMerger(fragMerge); // don't cheat
org.lcsim.recon.cluster.structural.CheatFragmentMerger cheatFragMerge = new org.lcsim.recon.cluster.structural.CheatFragmentMerger();
cheatFragMerge.initializeAssociator("TmpHitList", "TmpClusterList", mcListName, "TmpMCCList", "TmpCMCList");
add(cheatFragMerge);
- fragMergeDriver.setFragmentMerger(cheatFragMerge); // cheat
+ //fragMergeDriver.setFragmentMerger(cheatFragMerge); // cheat [broken?]
add(fragMergeDriver);
accountant.addListOfNamedLists( new String[] { "ecal hit map after mst", "hcal hit map after mst", "clusters with fragments merged", "hits left over after fragment merge", "photon particles" } );
// Repeat the hadron ID step with the revised cluster list:
- SimpleChargedParticleMaker hadID2 = new SimpleChargedParticleMaker();
- hadID2.setInputTrackList(EventHeader.TRACKS);
- hadID2.setOutputTrackList("leftover tracks 2");
- hadID2.setInputMIPList("mips");
- hadID2.setInputClusterList("clusters with fragments merged");
- hadID2.setOutputParticleList("charged hadron particles 2");
- add(hadID2);
+
+ // First try the MIPs...
+ {
+ MIPChargedParticleMaker hadIDmip2 = new MIPChargedParticleMaker();
+ SimpleTrackMIPClusterMatcher mipMatch = new SimpleTrackMIPClusterMatcher();
+ add(mipMatch);
+ hadIDmip2.setTrackMatcher(mipMatch);
+ hadIDmip2.setInputTrackList(trackList);
+ hadIDmip2.setOutputTrackList("tracks minus mip associations 2");
+ hadIDmip2.setInputMIPList("mips");
+ hadIDmip2.setOutputParticleList("charged hadron particles with mip association 2");
+ hadIDmip2.setOutputMIPList("unmatched mips 2");
+ hadIDmip2.addClusterList("clusters with fragments merged", "clusters with fragments merged minus charged particles from mips");
+ add(hadIDmip2);
+ }
+
+ // Then try the clusters generically:
+ {
+ SimpleChargedParticleMaker hadID2 = new SimpleChargedParticleMaker();
+ SimpleTrackClusterMatcher clusMatch = new SimpleTrackClusterMatcher();
+ add(clusMatch);
+ hadID2.setTrackMatcher(clusMatch);
+ hadID2.setInputTrackList("tracks minus mip associations 2");
+ hadID2.setOutputTrackList("leftover tracks 2");
+ hadID2.setInputClusterList("clusters with fragments merged minus charged particles from mips");
+ hadID2.setOutputParticleList("charged hadron particles with non-mip association 2");
+ add(hadID2);
+ }
+
+ // Merge the two particle lists:
+ {
+ ListAddDriver<ReconstructedParticle> mergeParticles = new ListAddDriver<ReconstructedParticle>();
+ mergeParticles.addInputList("charged hadron particles with mip association 2");
+ mergeParticles.addInputList("charged hadron particles with non-mip association 2");
+ mergeParticles.setOutputList("charged hadron particles 2");
+ add(mergeParticles);
+ }
+
// ... and then any remaining clusters should be neutral
ClusterListFilterDriver removeChargedClusters = new ClusterListFilterDriver();
VetoClustersFromParticles vetoCharged = new VetoClustersFromParticles("charged hadron particles 2");