Print

Print


Commit in lcsim-contrib/src/main/java/org/lcsim/contrib/Cassell/recon on MAIN
TestSetUpDTreeForReclustering.java+374added 1.1
TestSetUpPFA.java+122added 1.1
PostTrackingTestReconDriver.java+47added 1.1
photons/RemoveHitsNearTracks.java+98added 1.1
       /TestPhotonFinder.java+162added 1.1
+803
5 added files
Test programs for photon finding development

lcsim-contrib/src/main/java/org/lcsim/contrib/Cassell/recon
TestSetUpDTreeForReclustering.java added at 1.1
diff -N TestSetUpDTreeForReclustering.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ TestSetUpDTreeForReclustering.java	14 Mar 2011 17:34:02 -0000	1.1
@@ -0,0 +1,374 @@
+package org.lcsim.contrib.Cassell.recon;
+
+import org.lcsim.recon.pfa.structural.*;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.lcsim.event.CalorimeterHit;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.Cluster;
+import org.lcsim.recon.cluster.directedtree.DirectedTreeDriver;
+import org.lcsim.recon.cluster.mipfinder.ShowerPointFinderDriver;
+import org.lcsim.recon.cluster.mipfinder.ShowerPointFinderDriver2;
+import org.lcsim.recon.cluster.mipfinder.trackxtrap.*;
+import org.lcsim.recon.cluster.muonfinder.MuonFinderWrapper;
+import org.lcsim.recon.cluster.muonfinder.MuonFinderWrapper3;
+import org.lcsim.recon.cluster.util.HitNearBarrelEndcapBoundaryDecision;
+import org.lcsim.recon.cluster.util.RemoveHitsFromClusters;
+import org.lcsim.recon.cluster.util.VetoHitsFromClusters;
+import org.lcsim.recon.cluster.util.ClusterMapSubtractDriver;
+import org.lcsim.recon.pfa.identifier.AmbiguousTrackToClusterMapMaker;
+import org.lcsim.recon.pfa.identifier.HelixExtrapolator;
+import org.lcsim.recon.pfa.identifier.TrackToElectronMapMaker;
+import org.lcsim.recon.pfa.identifier.TrackToGenericClusterMapMaker;
+import org.lcsim.recon.pfa.identifier.TrackToMipClusterMapMaker;
+import org.lcsim.recon.pfa.identifier.TrackToPreShowerMipMapMaker;
+import org.lcsim.util.Driver;
+import org.lcsim.util.ListAddDriver;
+import org.lcsim.util.ListSubtractDriver;
+import org.lcsim.util.TransientFlagDriver;
+import org.lcsim.util.decision.ListFilterDriver;
+import org.lcsim.util.hitmap.ClusterListToHitMapDriver;
+import org.lcsim.util.hitmap.HitListToHitMapDriver;
+import org.lcsim.util.hitmap.HitMapAddDriver;
+import org.lcsim.util.hitmap.HitMapAndDriver;
+import org.lcsim.util.hitmap.HitMapSubtractDriver;
+import org.lcsim.recon.util.CalorimeterInformation;
+import org.lcsim.geometry.Calorimeter.CalorimeterType;
+
+public class TestSetUpDTreeForReclustering extends Driver
+{
+    String inputTrackList;
+    Collection<String> allHitLists;
+    Collection<String> recoHitLists;
+    Collection<String> hitsForMST;
+    HelixExtrapolator findCluster;
+    boolean init;
+    boolean useNewInitialMipFinding = false;
+    public TestSetUpDTreeForReclustering(String inputTrackListi, Collection<String> allHitListsi, Collection<String> recoHitListsi, Collection<String> hitsForMSTi, HelixExtrapolator findClusteri) {
+        inputTrackList = inputTrackListi;
+        allHitLists = allHitListsi;
+        recoHitLists = recoHitListsi;
+        hitsForMST = hitsForMSTi;
+        findCluster = findClusteri;
+        init = false;
+    }
+    public void setUseNewInitialMipFinding(boolean x){useNewInitialMipFinding = x;}
+    protected void process(EventHeader event)
+    {
+        if(!init)
+        {
+            init = true;
+            CalorimeterInformation ci = CalorimeterInformation.instance();
+	// Convert DigiSim's lists to hitmaps:
+	Map<String,String> mapListToHitMap = new HashMap<String,String>();
+	for (String inputName : allHitLists) {
+	    String outputName = (new String(inputName)).replace("DigiHits", "DigiHitMap");
+	    mapListToHitMap.put(inputName, outputName);
+	    HitListToHitMapDriver converter = new HitListToHitMapDriver();
+	    converter.addInputList(inputName);
+	    converter.setOutput(outputName);
+	    add(converter);
+	}
+	// Convenience: Merge ECAL barrel & ECAL endcap
+	HitMapAddDriver combineEcal = new HitMapAddDriver();
+	combineEcal.addInputHitMap((new String(ci.getDigiCollectionName(CalorimeterType.EM_BARREL))).replace("DigiHits", "DigiHitMap"));
+	combineEcal.addInputHitMap((new String(ci.getDigiCollectionName(CalorimeterType.EM_ENDCAP))).replace("DigiHits", "DigiHitMap"));
+	combineEcal.setOutputHitMap("EcalDigiHitMap");
+	add(combineEcal);
+	// Convenience: Merge HCAL barrel & HCAL endcap
+	HitMapAddDriver combineHcal = new HitMapAddDriver();
+	combineHcal.addInputHitMap((new String(ci.getDigiCollectionName(CalorimeterType.HAD_BARREL))).replace("DigiHits", "DigiHitMap"));
+	combineHcal.addInputHitMap((new String(ci.getDigiCollectionName(CalorimeterType.HAD_ENDCAP))).replace("DigiHits", "DigiHitMap"));
+	combineHcal.setOutputHitMap("HcalDigiHitMap");
+	add(combineHcal);
+	// Make combined hitmap of all hits (for muon searches)
+	HitMapAddDriver combineAll = new HitMapAddDriver();
+	for (String inputName : allHitLists) {
+	    combineAll.addInputHitMap(mapListToHitMap.get(inputName));
+	    combineAll.setOutputHitMap("AllDigiHitMap");
+	}
+	add(combineAll);
+	// Make combined hitmap of all reconstructable hits
+	HitMapAddDriver combineReco = new HitMapAddDriver();
+	for (String inputName : recoHitLists) {
+	    combineReco.addInputHitMap(mapListToHitMap.get(inputName));
+	    combineReco.setOutputHitMap("RecoDigiHitMap");
+	}
+	add(combineReco);
+
+        // Extrapolate tracks through the calorimeters for later use
+        add(new TrackXtrapThruCalDriver(findCluster,inputTrackList,"TrackXtrapInfo"));
+
+	// Find photons in ECAL
+	{
+	    // We have to use ALL hits for the photon-finder -- this is because it uses the
+            // presence of hits in early layers to veto on charged particles.
+	    org.lcsim.contrib.Cassell.recon.photons.TestPhotonFinder photonFinder = new org.lcsim.contrib.Cassell.recon.photons.TestPhotonFinder("EcalDigiHitMap", "EcalDigiHitMapMinusPreliminaryPhotons", "PreliminaryPhotonClustersForDTree","PotentialElectronClusters");
+//	    org.lcsim.recon.cheater.CheatPhotonFinder chphotonFinder = new org.lcsim.recon.cheater.CheatPhotonFinder("EcalDigiHitMap", "Dummy", "CheatPhotonClustersForDTree");
+//	    add(chphotonFinder);
+	    add(photonFinder);
+	    add(new TransientFlagDriver("PreliminaryPhotonClustersForDTree"));
+	    add(new TransientFlagDriver("PotentialElectronClusters"));
+
+	    // Check for electrons and set those to one side so we don't accidentally cluster them or use their tracks:
+	    add(new TrackToElectronMapMaker(findCluster, "PotentialElectronClusters", inputTrackList, "MapElectronTracksToClusters", "TracksWithoutElectrons", "ElectronMapClusters"));
+	    add(new ClusterMapSubtractDriver("PreliminaryPhotonClustersForDTree", "ElectronMapClusters", "PreliminaryPhotonClustersForDTreeMinusElectrons"));
+	    add(new ClusterListToHitMapDriver("ElectronMapClusters", "ElectronHitMap"));
+	    add(new HitMapSubtractDriver("RecoDigiHitMap", "ElectronHitMap", "RecoDigiHitMapWithoutElectrons"));
+	    add(new HitMapSubtractDriver("AllDigiHitMap", "ElectronHitMap", "AllDigiHitMapWithoutElectrons"));
+	}
+
+        // Attach calorimeter hits to tracks, useful for finding/attaching mips
+        add(new AttachCalorimeterHitsDriver("TracksWithoutElectrons","RecoDigiHitMapWithoutElectrons","TrackXtrapInfo",20.));
+	{
+	    // Find muons
+            if(useNewInitialMipFinding)
+            {
+                MuonFinderWrapper3 muonFinder3 = new MuonFinderWrapper3("TrackXtrapInfo","TracksWithoutElectrons", "AllDigiHitMapWithoutElectrons", "MuonTrackClusterMap", "AllDigiHitMapWithoutElectronsOrMuons", "TracksWithoutElectronsOrMuons");
+                add(muonFinder3);
+            }
+            else
+            {
+                MuonFinderWrapper muonFinder = new MuonFinderWrapper(findCluster, "TracksWithoutElectrons", "AllDigiHitMapWithoutElectrons", "MuonTrackClusterMap", "AllDigiHitMapWithoutElectronsOrMuons", "TracksWithoutElectronsOrMuons");
+	    //muonFinder.skip(); // TEST
+                add(muonFinder);
+            }
+	    // Identify the muon hits within useable hit block
+	    add(new HitMapSubtractDriver("RecoDigiHitMapWithoutElectrons", "AllDigiHitMapWithoutElectronsOrMuons", "RecoDigiHitMapMuons"));
+	    // Non-muon hits within useable hit block
+	    add(new HitMapSubtractDriver("RecoDigiHitMapWithoutElectrons", "RecoDigiHitMapMuons", "RecoDigiHitMapWithoutElectronsOrMuons"));
+	}
+
+	{
+            if(useNewInitialMipFinding)
+            {
+                System.out.println("Using new initial mip finder");
+                ShowerPointFinderDriver2 showerFinder2ForHad =
+                    new ShowerPointFinderDriver2("RecoDigiHitMapWithoutElectronsOrMuons", "TracksWithoutElectronsOrMuons", "TrackXtrapInfo", "ShowerFinderMapTrackToMip", "RecoDigiHitMapWithoutElectronsOrMuonsOrMips", "ShowerFinderMips");
+                add(showerFinder2ForHad);
+            }
+            else
+            {
+                // TJ's pre-shower MIP-finder
+                ShowerPointFinderDriver showerFinder = new ShowerPointFinderDriver(findCluster, "RecoDigiHitMapWithoutElectronsOrMuons", "TracksWithoutElectronsOrMuons", "ShowerFinderMapTrackToMip", "RecoDigiHitMapWithoutElectronsOrMuonsOrMips", "ShowerFinderMips");
+                add(showerFinder);
+            }
+	    add(new CheckDisjoint("RecoDigiHitMapWithoutElectronsOrMuonsOrMips", "ShowerFinderMips"));
+	    // Steve's pre-shower MIP-finder
+	    // disabled for now -- //add(new ReclusterDriver.SteveMipWrapper());
+
+	    // Match tracks -> pre-shower MIPs (best possible linkage)
+	    add(new TrackToPreShowerMipMapMaker("ShowerFinderMapTrackToMip", "TracksWithoutElectronsOrMuons", "MapPreShowerMipTracksToClusterSeeds", "UnmatchedTracksAfterPreShowerMipMap", "PreShowerMipMatchMipClusters", "PreShowerMipMatchSmallClusters", "PreShowerMipMatchBlockClusters"));
+	    // At this point, we COULD take the unlinked MIP hits back out and recycle them
+	    // into the DTree clustering. (The unlinked MIPs are the ones where two the MIP
+	    // clusters of 2+ tracks overlapped, or where there were too few hits, or both.)
+	    add(new ClusterListToHitMapDriver("PreShowerMipMatchSmallClusters", "PreShowerMipMatchSmallClusterHits"));
+	    add(new ClusterListToHitMapDriver("PreShowerMipMatchBlockClusters", "PreShowerMipMatchBlockClusterHits"));
+	    HitMapAddDriver remergeBadMips = new HitMapAddDriver();
+	    remergeBadMips.addInputHitMap("PreShowerMipMatchSmallClusterHits");
+	    remergeBadMips.addInputHitMap("PreShowerMipMatchBlockClusterHits");
+	    remergeBadMips.addInputHitMap("RecoDigiHitMapWithoutElectronsOrMuonsOrMips");
+	    remergeBadMips.setOutputHitMap("RecoDigiHitMapWithoutElectronsOrMuonsOrGoodMips");
+	    add(remergeBadMips); // TEST
+	}
+
+	{
+	    // Now go back and ensure that no photon uses hits from a charged particle's MIP.
+	    // We can either remove those individual hits or veto entire clusters.
+	    boolean remove = false;
+	    boolean findVetoedPhotons = true;
+	    if (remove) {
+		add(new RemoveHitsFromClusters("PreliminaryPhotonClustersForDTreeMinusElectrons", "MuonTrackClusterMap", "PhotonsMinusMuonHits"));
+		add(new RemoveHitsFromClusters("PhotonsMinusMuonHits", "ShowerFinderMapTrackToMip", "PhotonClustersForDTree"));
+	    } else {
+		add(new VetoHitsFromClusters("PreliminaryPhotonClustersForDTreeMinusElectrons", "MuonTrackClusterMap", "PhotonsMinusMuonHits"));
+		add(new VetoHitsFromClusters("PhotonsMinusMuonHits", "ShowerFinderMapTrackToMip", "PhotonClustersForDTree"));
+		if (findVetoedPhotons) {
+		    // Test: pick out vetoed clusters
+		    add(new ListSubtractDriver("PreliminaryPhotonClustersForDTreeMinusElectrons", "PhotonClustersForDTree", "VetoedPhotonClusters"));
+		    add(new CheckDisjoint("PhotonClustersForDTree", "VetoedPhotonClusters"));
+		    add(new RemoveHitsFromClusters("VetoedPhotonClusters", "MuonTrackClusterMap", "VetoedPhotonClustersMinusMuonHits"));
+		    add(new RemoveHitsFromClusters("VetoedPhotonClustersMinusMuonHits", "ShowerFinderMapTrackToMip", "VetoedPhotonClustersMinusMuonHitsAndMipHits"));
+		    add(new ClusterListToHitMapDriver("VetoedPhotonClustersMinusMuonHitsAndMipHits", "PhotonVetoHitMap"));
+		}
+	    }
+	    add(new TransientFlagDriver("PhotonsMinusMuonHits"));
+	    add(new TransientFlagDriver("PhotonClustersForDTree"));
+
+	    // Identify which hits were used for photons, electrons
+	    add(new ClusterListToHitMapDriver("PhotonClustersForDTree", "PhotonHitMap"));
+	    add(new CheckDisjoint("ShowerFinderMips", "PhotonHitMap"));
+
+	    // Identify remaining hits not used for photons or muons or mips
+	    if (!remove && findVetoedPhotons) {
+		add(new HitMapSubtractDriver("RecoDigiHitMapWithoutElectronsOrMuonsOrGoodMips", "PhotonHitMap", "TmpRecoDigiHitMapWithoutElectronsOrMuonsOrMipsOrPhotons"));
+		add(new HitMapSubtractDriver("TmpRecoDigiHitMapWithoutElectronsOrMuonsOrMipsOrPhotons", "PhotonVetoHitMap", "RecoDigiHitMapWithoutElectronsOrMuonsOrMipsOrPhotons"));
+	    } else {
+		add(new HitMapSubtractDriver("RecoDigiHitMapWithoutElectronsOrMuonsOrGoodMips", "PhotonHitMap", "RecoDigiHitMapWithoutElectronsOrMuonsOrMipsOrPhotons")); // Remove Muon/MIP hits
+		//add(new HitMapSubtractDriver("RecoDigiHitMap", "PhotonHitMap", "RecoDigiHitMapWithoutMuonsOrMipsOrPhotons")); // Keep all non-photon hits
+	    }
+	    add(new CheckDisjoint("RecoDigiHitMapWithoutElectronsOrMuonsOrMipsOrPhotons", "PhotonHitMap"));
+	}
+
+	// Run DTree on each subdetector separately:
+	Map<String,String> mapInputListToDTreeClusterList = new HashMap<String,String>();
+	for (String rawInputName : recoHitLists) {
+	    String rawInputHitMapName = mapListToHitMap.get(rawInputName);
+	    String filteredInputHitMapName = (new String(rawInputName)).replace("DigiHits", "DigiHitMapForDTree");
+	    String outputHitMapName = new String(rawInputHitMapName+"AfterDTree");
+	    String outputClusterListName = new String(rawInputHitMapName+"Clusters");
+	    mapInputListToDTreeClusterList.put(rawInputName, outputClusterListName);
+	    // Filter hitmap to only contain hits from this subdet that are not muon/mip/photon hits
+	    add(new HitMapAndDriver(rawInputHitMapName, "RecoDigiHitMapWithoutElectronsOrMuonsOrMipsOrPhotons", filteredInputHitMapName));
+	    if (hitsForMST.contains(rawInputName)) {
+		// Run MST
+		org.lcsim.recon.cluster.mst.MSTClusterDriver mstDriver = new org.lcsim.recon.cluster.mst.MSTClusterDriver(outputHitMapName, outputClusterListName);
+		mstDriver.addInputHitMap(filteredInputHitMapName);
+		mstDriver.setThreshold(1500.0); // FIXME: This is not optimal
+		mstDriver.registerMetrics(new org.lcsim.recon.cluster.mst.MinimumHitToHitDistance());
+		add(mstDriver);
+	    } else {
+                if(outputClusterListName.contains("Muon"))
+                {
+                    // Don't know how this ever worked for muons!
+                    // Fake it with nn
+                    FakeDTDriver treeDriver = new FakeDTDriver(5,5,2,0,0.);
+                    treeDriver.setInputHitMap(filteredInputHitMapName);
+                    treeDriver.setOutputClusterList(outputClusterListName);
+                    add(treeDriver);
+                }
+                else
+                {
+		// Run DTree
+		DirectedTreeDriver treeDriver = new DirectedTreeDriver();
+		treeDriver.setInputHitMap(filteredInputHitMapName);
+		treeDriver.setOutputClusterList(outputClusterListName);
+		treeDriver.setOutputHitMap(outputHitMapName);
+		add(treeDriver);
+                }
+	    }
+	    add(new TransientFlagDriver(outputClusterListName));
+	}
+
+	// Merge/categorize & write out
+	ListAddDriver<Cluster> mergeDTreeClustersECAL = new ListAddDriver<Cluster>(Cluster.class);
+	ListAddDriver<Cluster> mergeDTreeClustersHCAL = new ListAddDriver<Cluster>(Cluster.class);
+	ListAddDriver<Cluster> mergeDTreeClustersMCAL = new ListAddDriver<Cluster>(Cluster.class);
+	ListAddDriver<Cluster> mergeDTreeClustersAll  = new ListAddDriver<Cluster>(Cluster.class);
+	for (String inputName : recoHitLists) {
+	    String clusterListName = mapInputListToDTreeClusterList.get(inputName);
+	    mergeDTreeClustersAll.addInputList(clusterListName);
+	    if( (inputName.compareTo(ci.getDigiCollectionName(CalorimeterType.EM_BARREL))==0)||
+	        (inputName.compareTo(ci.getDigiCollectionName(CalorimeterType.EM_ENDCAP))==0)
+          ){
+            mergeDTreeClustersECAL.addInputList(clusterListName);
+	    }
+        else if( (inputName.compareTo(ci.getDigiCollectionName(CalorimeterType.HAD_BARREL))==0)||
+	        (inputName.compareTo(ci.getDigiCollectionName(CalorimeterType.HAD_ENDCAP))==0)
+          ){
+            mergeDTreeClustersHCAL.addInputList(clusterListName);
+	    }
+        else if( (inputName.contains("Muon"))
+          ){
+            mergeDTreeClustersMCAL.addInputList(clusterListName);
+	    }
+	}
+	mergeDTreeClustersECAL.setOutputList("DTreeClustersECAL");
+	mergeDTreeClustersHCAL.setOutputList("DTreeClustersHCAL");
+	mergeDTreeClustersMCAL.setOutputList("DTreeClustersMCAL");
+	mergeDTreeClustersAll .setOutputList("DTreeClustersAll");
+	add(mergeDTreeClustersECAL);
+	add(mergeDTreeClustersHCAL);
+	add(mergeDTreeClustersMCAL);
+	add(mergeDTreeClustersAll);
+	add(new TransientFlagDriver("DTreeClustersECAL"));
+	add(new TransientFlagDriver("DTreeClustersHCAL"));
+	add(new TransientFlagDriver("DTreeClustersMCAL"));
+	add(new TransientFlagDriver("DTreeClustersAll"));
+
+	// RZ. Merge DTrees crossing sub-detector boundaries
+	add(new MergeClustersCrossingSubDetectorBoundaries("DTreeClustersAll", "DTreeClusters"));
+	add(new TransientFlagDriver("DTreeClusters"));
+	add(new TransientFlagDriver("DTreeClustersOriginal"));
+
+	// OK, now go back and look for hits near boundaries (for use when making MIPs
+	// with a layer-based algorithm so it can cross from endcap to barrel).
+	{
+	    HitNearBarrelEndcapBoundaryDecision dec = new HitNearBarrelEndcapBoundaryDecision(6.0, 15.0, 1);
+	    add(dec);
+	    add(new ListFilterDriver(dec,ci.getDigiCollectionName(CalorimeterType.EM_BARREL), "EcalBarrelDigiHitsNearBoundary", CalorimeterHit.class));
+	    add(new ListFilterDriver(dec,ci.getDigiCollectionName(CalorimeterType.HAD_BARREL), "HcalBarrelDigiHitsNearBoundary", CalorimeterHit.class));
+	    add(new ListFilterDriver(dec,ci.getDigiCollectionName(CalorimeterType.EM_ENDCAP), "EcalEndcapDigiHitsNearBoundary", CalorimeterHit.class));
+	    add(new ListFilterDriver(dec,ci.getDigiCollectionName(CalorimeterType.HAD_ENDCAP), "HcalEndcapDigiHitsNearBoundary", CalorimeterHit.class));
+	    add(new TransientFlagDriver("EcalBarrelDigiHitsNearBoundary"));
+	    add(new TransientFlagDriver("HcalBarrelDigiHitsNearBoundary"));
+	    add(new TransientFlagDriver("EcalEndcapDigiHitsNearBoundary"));
+	    add(new TransientFlagDriver("HcalEndcapDigiHitsNearBoundary"));
+	}
+
+	// Look for substructure inside clusters:
+	{
+	    int m_minHitsToBeTreatedAsClusterECAL = 15;
+	    int m_minHitsToBeTreatedAsClusterHCAL = 20;
+	    int m_minHitsToBeTreatedAsClusterMCAL = 5;
+	    int m_minHitsToBeTreatedAsClusterFCAL = m_minHitsToBeTreatedAsClusterECAL;
+	    double m_newMipFinderRadiusECAL = 20.0;
+	    double m_newMipFinderRadiusHCAL = 50.0;
+	    double m_newMipFinderRadiusMCAL = 100.0;
+	    double m_newMipFinderRadiusFCAL = m_newMipFinderRadiusECAL;
+	    boolean m_removePoorQualityMips = false;
+
+	    FindSubClusters clusDriverECAL = new FindSubClusters("DTreeClustersECAL", m_newMipFinderRadiusECAL, m_minHitsToBeTreatedAsClusterECAL, m_removePoorQualityMips, "OldMipsInsideTreesECAL", "NewMipsInsideTreesECAL", "ClumpsInsideTreesECAL", "BlocksInsideTreesECAL", "LeftoverHitsInsideTreesECAL", "MapTreeToTargetsECAL", "MapSharedToTreeECAL");
+	    FindSubClusters clusDriverHCAL = new FindSubClusters("DTreeClustersHCAL", m_newMipFinderRadiusHCAL, m_minHitsToBeTreatedAsClusterHCAL, m_removePoorQualityMips, "OldMipsInsideTreesHCAL", "NewMipsInsideTreesHCAL", "ClumpsInsideTreesHCAL", "BlocksInsideTreesHCAL", "LeftoverHitsInsideTreesHCAL", "MapTreeToTargetsHCAL", "MapSharedToTreeHCAL");
+	    FindSubClusters clusDriverMCAL = new FindSubClusters("DTreeClustersMCAL", m_newMipFinderRadiusMCAL, m_minHitsToBeTreatedAsClusterMCAL, m_removePoorQualityMips, "OldMipsInsideTreesMCAL", "NewMipsInsideTreesMCAL", "ClumpsInsideTreesMCAL", "BlocksInsideTreesMCAL", "LeftoverHitsInsideTreesMCAL", "MapTreeToTargetsMCAL", "MapSharedToTreeMCAL");
+	    //FindSubClusters clusDriverFCAL = new FindSubClusters("DTreeClustersFCAL", m_newMipFinderRadiusFCAL, m_minHitsToBeTreatedAsClusterFCAL, m_removePoorQualityMips, "OldMipsInsideTreesFCAL", "NewMipsInsideTreesFCAL", "ClumpsInsideTreesFCAL", "BlocksInsideTreesFCAL", "LeftoverHitsInsideTreesFCAL", "MapTreeToTargetsFCAL", "MapSharedToTreeFCAL");
+	    clusDriverECAL.enableBarrelEndcapCrossing(ci.getDigiCollectionName(CalorimeterType.EM_BARREL), "EcalBarrelDigiHitsNearBoundary",ci.getDigiCollectionName(CalorimeterType.EM_ENDCAP), "EcalEndcapDigiHitsNearBoundary");
+	    clusDriverHCAL.enableBarrelEndcapCrossing(ci.getDigiCollectionName(CalorimeterType.HAD_BARREL), "HcalBarrelDigiHitsNearBoundary",ci.getDigiCollectionName(CalorimeterType.HAD_ENDCAP), "HcalEndcapDigiHitsNearBoundary");
+	    clusDriverECAL.setNNrange(1,1,1);
+	    clusDriverHCAL.setNNrange(2,2,1);
+	    clusDriverMCAL.setNNrange(2,2,1);
+	    //clusDriverFCAL.setNNrange(1,1,1);
+	    add(clusDriverECAL);
+	    add(clusDriverHCAL);
+	    add(clusDriverMCAL);
+	}
+
+	// Track-cluster matching in steps:
+	// Already done electrons, muons, and good pre-shower MIPs.
+	// Now take a go at the rest...
+
+	// Match tracks to MIP clusters in ECAL (ambiguities not allowed)
+	TrackToMipClusterMapMaker mipMapMaker = new TrackToMipClusterMapMaker(findCluster, "UnmatchedTracksAfterPreShowerMipMap", "MapMipClusterTracksToClusterSeeds", "UnmatchedTracksAfterMipClusterMap");
+	mipMapMaker.addInputList("OldMipsInsideTreesECAL", "MipMatchedOldMipsInsideTreesECAL", "UnmatchedOldMipsInsideTreesECALAfterMipMatch");
+	mipMapMaker.addInputList("NewMipsInsideTreesECAL", "MipMatchedNewMipsInsideTreesECAL", "UnmatchedNewMipsInsideTreesECALAfterMipMatch");
+	add(mipMapMaker);
+	// Match tracks to generic clusters in ECAL
+	TrackToGenericClusterMapMaker genMapMaker = new TrackToGenericClusterMapMaker(findCluster, "UnmatchedTracksAfterMipClusterMap", "MapGenClusterTracksToClusterSeeds", "UnmatchedTracksAfterGenClusterMap");
+	genMapMaker.addInputList("UnmatchedOldMipsInsideTreesECALAfterMipMatch", "GenMatchedOldMipsInsideTreesECAL", "UnmatchedOldMipsInsideTreesECALAfterGenMatch");
+	genMapMaker.addInputList("UnmatchedNewMipsInsideTreesECALAfterMipMatch", "GenMatchedNewMipsInsideTreesECAL", "UnmatchedNewMipsInsideTreesECALAfterGenMatch");
+	genMapMaker.addInputList("ClumpsInsideTreesECAL", "GenMatchedClumpsInsideTreesECAL", "UnmatchedClumpsInsideTreesECALAfterGenMatch");
+	genMapMaker.addInputList("BlocksInsideTreesECAL", "GenMatchedBlocksInsideTreesECAL", "UnmatchedBlocksInsideTreesECALAfterGenMatch");
+	genMapMaker.addInputList("LeftoverHitsInsideTreesECAL", "GenMatchedLeftoverHitsInsideTreesECAL", "UnmatchedLeftoverHitsInsideTreesECALAfterGenMatch");
+	genMapMaker.addInputList("PhotonClustersForDTree", "GenMatchedPhotonClustersForDTree", "UnmatchedPhotonClustersForDTreeAfterGenMatch");
+	add(genMapMaker);
+	// [here: can split photon seeds, large seeds, etc...]
+	// Remaining tracks have either NO match or an ambiguous one (i.e. >1 track to same cluster
+	AmbiguousTrackToClusterMapMaker ambiguousMapMaker = new AmbiguousTrackToClusterMapMaker(findCluster, "UnmatchedTracksAfterGenClusterMap", "MapAmbigClusterTracksToClusterSeeds", "UnmatchedTracksAfterAmbigClusterMap");
+	ambiguousMapMaker.addInputList("UnmatchedOldMipsInsideTreesECALAfterGenMatch", "AmbigMatchedOldMipsInsideTreesECAL", "UnmatchedOldMipsInsideTreesECALAfterAmbigMatch");
+	ambiguousMapMaker.addInputList("UnmatchedNewMipsInsideTreesECALAfterGenMatch", "AmbigMatchedNewMipsInsideTreesECAL", "UnmatchedNewMipsInsideTreesECALAfterAmbigMatch");
+	ambiguousMapMaker.addInputList("UnmatchedClumpsInsideTreesECALAfterGenMatch", "AmbigMatchedClumpsInsideTreesECAL", "UnmatchedClumpsInsideTreesECALAfterAmbigMatch");
+	ambiguousMapMaker.addInputList("UnmatchedBlocksInsideTreesECALAfterGenMatch", "AmbigMatchedBlocksInsideTreesECAL", "UnmatchedBlocksInsideTreesECALAfterAmbigMatch");
+	ambiguousMapMaker.addInputList("UnmatchedLeftoverHitsInsideTreesECALAfterGenMatch", "AmbigMatchedLeftoverHitsInsideTreesECAL", "UnmatchedLeftoverHitsInsideTreesECALAfterAmbigMatch");
+	ambiguousMapMaker.addInputList("UnmatchedPhotonClustersForDTreeAfterGenMatch", "AmbigMatchedPhotonClustersForDTree", "UnmatchedPhotonClustersForDTreeAfterAmbigMatch");
+	add(ambiguousMapMaker);
+	// [here: can try to split large seeds with >1 track]
+        }
+        long start = System.currentTimeMillis();
+        super.process(event);
+        long end = System.currentTimeMillis();
+        double cput = (double)(end-start)/1000.;
+        System.out.println("Processing SetUpDTreeForReclustering took "+cput+" secs");
+    }
+}

lcsim-contrib/src/main/java/org/lcsim/contrib/Cassell/recon
TestSetUpPFA.java added at 1.1
diff -N TestSetUpPFA.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ TestSetUpPFA.java	14 Mar 2011 17:34:02 -0000	1.1
@@ -0,0 +1,122 @@
+package org.lcsim.contrib.Cassell.recon;
+
+import org.lcsim.recon.pfa.structural.*;
+import java.util.*;
+import org.lcsim.util.*;
+import org.lcsim.event.*;
+import org.lcsim.util.decision.*;
+import org.lcsim.recon.pfa.identifier.*;
+import org.lcsim.recon.cluster.util.CalorimeterHitTimeCutDecision;
+import org.lcsim.recon.cluster.util.UpperSubLayerDecision;
+import org.lcsim.recon.util.CalorimeterInformation;
+import org.lcsim.geometry.Calorimeter.CalorimeterType;
+
+public class TestSetUpPFA extends Driver {
+
+    //default 250 GeV
+    UnphysicalTrackDecision dec = new UnphysicalTrackDecision();
+    //default input realistic tracks
+    ListFilterDriver fil = new ListFilterDriver(dec,"Tracks", "FilteredTrackList", Track.class);
+    HelixExtrapolator findCluster = new org.lcsim.recon.pfa.identifier.TrackHelixPlusHitExtrapolator();
+    ReclusterDTreeDriver reclusTree = new ReclusterDTreeDriver("DTreeClusters", "UnmatchedTracksAfterAmbigClusterMap", "ReconFSParticles", "MuonTrackClusterMap", findCluster);
+
+    public void setFilterInputTrack(String x){ fil.setInputList(x); }
+    public void setFilterDefaultValue(double x){ dec.setDefaultvalue(x); }
+    public void setFilterOnputTrack(String x){ fil.setOutputList(x); }
+    public void setReclusJetScoreThreshold(double x){ reclusTree.setJetScoreThreshold(x); }
+    public void setReclusJetTolerance(double x){ reclusTree.setJetTolerance(x); }
+    public void setReclusMinScoreForReassignment(double x){ reclusTree.setMinScoreForReassignment(x); }
+    public void setReclusUseMucalBarrel(boolean x){ reclusTree.setUseMucalBarrel(x); }
+    public void setReclusUseMucalEndcap(boolean x){ reclusTree.setUseMucalEndcap(x); }
+    public void setReclusUseAnalogHcalCalibration(boolean x){ reclusTree.setUseAnalogHcalCalibration(x); }
+    public void setReclusPunchThroughLayers(int x){ reclusTree.setPunchThroughLayers(x); }
+    public void setReclusPunchThroughHitMinimum(int x){ reclusTree.setPunchThroughHitMinimum(x); }
+    public void setReclusCheckSharedHitsForPunchThrough(boolean x){ reclusTree.setCheckSharedHitsForPunchThrough(x); }
+    public void setReclusOutputParticleListName(String x){ reclusTree.setOutputParticleListName(x); }
+    private boolean init;
+    private boolean useNewInitialMipFinding = false;
+    public void setUseNewInitialMipFinding(boolean x){useNewInitialMipFinding = x;}
+
+
+    public TestSetUpPFA(){
+        this("Tracks");
+    }
+
+    public TestSetUpPFA(String trackList) {
+	// Filter tracks, removing those with unphysical energy
+	{
+            fil.setInputList(trackList);
+	    add(dec);
+            add(fil);        
+            init = false;
+	}
+    }
+
+    protected void process(EventHeader event)
+    {
+        if(!init)
+        {
+            init = true;
+            CalorimeterInformation ci = CalorimeterInformation.instance();
+            // Filter muon system hits
+
+            {
+                DecisionMakerSingle<CalorimeterHit> upperLayer = new UpperSubLayerDecision();
+                DecisionMakerSingle<CalorimeterHit> lowerLayer = new NotDecisionMakerSingle(upperLayer);
+                DecisionMakerSingle<CalorimeterHit> timeCut = new CalorimeterHitTimeCutDecision(100);
+                AndDecisionMakerSingle<CalorimeterHit> lowerLayerAndTimeCut = new AndDecisionMakerSingle<CalorimeterHit>();
+                lowerLayerAndTimeCut.addDecisionMaker(lowerLayer);
+                lowerLayerAndTimeCut.addDecisionMaker(timeCut);
+                add(new ListFilterDriver(lowerLayerAndTimeCut, ci.getCollectionName(CalorimeterType.MUON_BARREL), "CorrMuonBarrelDigiHits", CalorimeterHit.class));
+                add(new ListFilterDriver(lowerLayerAndTimeCut, ci.getCollectionName(CalorimeterType.MUON_ENDCAP), "CorrMuonEndcapDigiHits", CalorimeterHit.class));
+            }
+
+            // Set up track extrapolation
+            add(findCluster);
+
+            // Set up input lists of calorimeter hits
+            {
+                List<String> recoHitLists = new Vector<String>(); // Hits to use in main clustering
+                List<String> allHitLists = new Vector<String>(); // All hits (used in muon-finding)
+                List<String> mstHitLists = new Vector<String>(); // Hits from subsystems where we have to use MST
+                recoHitLists.add(ci.getDigiCollectionName(CalorimeterType.EM_BARREL));
+                recoHitLists.add(ci.getDigiCollectionName(CalorimeterType.EM_ENDCAP));
+                recoHitLists.add(ci.getDigiCollectionName(CalorimeterType.HAD_BARREL));
+                recoHitLists.add(ci.getDigiCollectionName(CalorimeterType.HAD_ENDCAP));
+                recoHitLists.add("CorrMuonEndcapDigiHits");
+                allHitLists.addAll(recoHitLists);
+                allHitLists.add("CorrMuonBarrelDigiHits");
+                mstHitLists.add(ci.getDigiCollectionName(CalorimeterType.MUON_ENDCAP));
+                TestSetUpDTreeForReclustering setup = new TestSetUpDTreeForReclustering("FilteredTrackList", allHitLists, recoHitLists, mstHitLists, findCluster);
+                setup.setUseNewInitialMipFinding(useNewInitialMipFinding);
+                add(setup);
+            }
+
+            // Set up and run PFA
+            reclusTree.writeExtraEventOutput(false);
+            reclusTree.addInputMips("OldMipsInsideTreesECAL");
+            reclusTree.addInputMips("NewMipsInsideTreesECAL");
+            reclusTree.addInputMips("OldMipsInsideTreesHCAL");
+            reclusTree.addInputMips("NewMipsInsideTreesHCAL");
+            reclusTree.addInputMips("OldMipsInsideTreesMCAL");
+            reclusTree.addInputMips("NewMipsInsideTreesMCAL");
+            reclusTree.addInputMips("PreShowerMipMatchMipClusters");
+            reclusTree.addInputClumps("ClumpsInsideTreesECAL");
+            reclusTree.addInputClumps("ClumpsInsideTreesHCAL");
+            reclusTree.addInputClumps("ClumpsInsideTreesMCAL");
+            reclusTree.addInputBlocks("BlocksInsideTreesECAL");
+            reclusTree.addInputBlocks("BlocksInsideTreesHCAL");
+            reclusTree.addInputBlocks("BlocksInsideTreesMCAL");
+            reclusTree.addInputLeftoverHits("LeftoverHitsInsideTreesECAL");
+            reclusTree.addInputLeftoverHits("LeftoverHitsInsideTreesHCAL");
+            reclusTree.addInputLeftoverHits("LeftoverHitsInsideTreesMCAL");
+            reclusTree.addTrackToClusterMap("MapPreShowerMipTracksToClusterSeeds");
+            reclusTree.addTrackToClusterMap("MapMipClusterTracksToClusterSeeds");
+            reclusTree.addTrackToClusterMap("MapGenClusterTracksToClusterSeeds");
+            reclusTree.addTrackToClusterMap("MapAmbigClusterTracksToClusterSeeds");
+//            reclusTree.setDebug(true);
+            add(reclusTree);
+        }
+        super.process(event);
+    }
+}

lcsim-contrib/src/main/java/org/lcsim/contrib/Cassell/recon
PostTrackingTestReconDriver.java added at 1.1
diff -N PostTrackingTestReconDriver.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ PostTrackingTestReconDriver.java	14 Mar 2011 17:34:02 -0000	1.1
@@ -0,0 +1,47 @@
+package org.lcsim.contrib.Cassell.recon;
+
+import org.lcsim.digisim.DigiPackageDriver;
+import org.lcsim.recon.pfa.output.FlushReconstructedParticlesDriver;
+import org.lcsim.recon.pfa.structural.SetUpPFA;
+import org.lcsim.recon.util.CalInfoDriver;
+import org.lcsim.util.Driver;
+
+/**
+ * Top-level driver to run UI PFA reconstruction.
+ * 
+ * @author cassell
+ * @version $Id: PostTrackingTestReconDriver.java,v 1.1 2011/03/14 17:34:02 cassell Exp $
+ */
+
+public class PostTrackingTestReconDriver extends Driver
+{
+    private boolean useNewInitialMipFinding = false;
+    TestSetUpPFA setup;
+    public void setUseNewInitialMipFinding(boolean x)
+    {
+        useNewInitialMipFinding = x;
+        setup.setUseNewInitialMipFinding(useNewInitialMipFinding);
+    }
+    /** 
+     * Constructor that sets up daughter drivers. 
+     */
+    public PostTrackingTestReconDriver()
+    {
+        // Cash general calorimeter information
+        add(new CalInfoDriver());
+
+    	// Run digisim.
+        add(new DigiPackageDriver());
+        
+        // Run tracking.
+//        add(new org.lcsim.recon.tracking.seedtracker.trackingdrivers.sidloi2.MainTrackingDriver());
+	
+        // Set up and run PFA.
+        setup = new TestSetUpPFA("Tracks");
+        setup.setUseNewInitialMipFinding(useNewInitialMipFinding);
+        add(setup);
+
+        // Output collections.
+        add(new FlushReconstructedParticlesDriver("DTreeReclusteredParticles", "ReconstructedParticles", "Clusters"));
+    }
+}

lcsim-contrib/src/main/java/org/lcsim/contrib/Cassell/recon/photons
RemoveHitsNearTracks.java added at 1.1
diff -N RemoveHitsNearTracks.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ RemoveHitsNearTracks.java	14 Mar 2011 17:34:02 -0000	1.1
@@ -0,0 +1,98 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+package org.lcsim.contrib.Cassell.recon.photons;;
+import java.util.*;
+import org.lcsim.util.Driver;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.CalorimeterHit;
+import org.lcsim.event.Cluster;
+import org.lcsim.recon.cluster.util.BasicCluster;
+import org.lcsim.recon.cluster.mipfinder.trackxtrap.*;
+import hep.physics.vec.*;
+import org.lcsim.geometry.Calorimeter.CalorimeterType;
+import org.lcsim.util.lcio.LCIOConstants;
+
+/**
+ *
+ * @author cassell
+ */
+public class RemoveHitsNearTracks extends Driver
+{
+    String inName;
+    String outName1;
+    String outName2;
+    String outmapName;
+    List<TrackXtrapInfo> txil;
+    protected double hitDsqCut = 7.*7.;// 2 cells
+    public RemoveHitsNearTracks(String in,String out1,String out2,String outmap)
+    {
+        inName = in;
+        outName1 = out1;
+        outName2 = out2;
+        outmapName = outmap;
+    }
+    protected void process(EventHeader event)
+    {
+        List<Cluster> inCl = event.get(Cluster.class,inName);
+        List<Cluster> outCl1 = new ArrayList<Cluster>();
+        List<Cluster> outCl2 = new ArrayList<Cluster>();
+        Map<Cluster,Cluster> outMap = new HashMap<Cluster,Cluster>();
+        txil = event.get(TrackXtrapInfo.class,"TrackXtrapInfo");
+        List<Hep3Vector> hitpos = new ArrayList<Hep3Vector>();
+        for(TrackXtrapInfo txi:txil)
+        {
+            for(XtrapPosition xi:txi.getPositions())
+            {
+                if( (xi.getCalorimeterType() == CalorimeterType.EM_BARREL)||
+                    (xi.getCalorimeterType() == CalorimeterType.EM_ENDCAP))
+                {
+                    hitpos.add(xi.getPosition());
+                }
+            }
+        }
+        for(Cluster c:inCl)
+        {
+            Cluster cutc = removeHits(c,hitpos);
+            if(c.getCalorimeterHits().size() == cutc.getCalorimeterHits().size())
+            {
+                outCl1.add(cutc);
+            }
+            else
+            {
+                if(cutc.getCalorimeterHits().size() > 0)outCl1.add(cutc);
+                outCl2.add(c);
+                outMap.put(c, cutc);
+            }
+        }
+        int flag = 1<<LCIOConstants.CLBIT_HITS;
+        event.put(outName1, outCl1, Cluster.class, flag );
+        event.put(outName2, outCl2, Cluster.class, flag );
+        event.put(outmapName,outMap);
+    }
+    public Cluster removeHits(Cluster c,List<Hep3Vector> hitpos)
+    {
+        BasicCluster newc = new BasicCluster();
+        newc.addCluster(c);
+        List<CalorimeterHit> remove = new ArrayList<CalorimeterHit>();
+        for(CalorimeterHit h:c.getCalorimeterHits())
+        {
+            Hep3Vector pos = h.getPositionVec();
+            for(Hep3Vector hpos:hitpos)
+            {
+                if(VecOp.sub(hpos, pos).magnitudeSquared() < hitDsqCut)
+                {
+                    remove.add(h);
+                    break;
+                }
+            }
+        }
+        for(CalorimeterHit h:remove)
+        {
+            newc.removeHit(h);
+        }
+        return newc;
+    }
+}

lcsim-contrib/src/main/java/org/lcsim/contrib/Cassell/recon/photons
TestPhotonFinder.java added at 1.1
diff -N TestPhotonFinder.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ TestPhotonFinder.java	14 Mar 2011 17:34:02 -0000	1.1
@@ -0,0 +1,162 @@
+/*
+ * RonDTPhotonFinderSid01.java
+ *
+ * Created on February 25, 2008, 10:28 AM
+ *
+ */
+
+package org.lcsim.contrib.Cassell.recon.photons;
+
+import org.lcsim.recon.pfa.photonfinder.*;
+import java.util.*;
+import org.lcsim.util.Driver;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.CalorimeterHit;
+import org.lcsim.event.Cluster;
+import org.lcsim.util.hitmap.HitMap;
+import org.lcsim.recon.cluster.nn.*;
+import org.lcsim.digisim.*;
+import org.lcsim.recon.cluster.util.*;
+import org.lcsim.util.lcio.LCIOConstants;
+import org.lcsim.recon.cluster.directedtree.*;
+import org.lcsim.recon.util.CalorimeterInformation;
+import org.lcsim.geometry.Calorimeter.CalorimeterType;
+
+/**
+ *
+ * @author cassell
+ */
+public class TestPhotonFinder extends Driver
+{
+    String inName;
+    String outHName;
+    String outCName1;
+    String outCName2;
+    String outMapName;
+    HMatrixVars hmv;
+    Sid01DTPhotonFinder finder;
+    String[] clusternames1;
+    String DTclName = "DTEcalClusters";
+    String ReDTclName = "Re"+DTclName;
+    Clusterer clusterer;
+    boolean init;
+    
+    /** Creates a new instance of RonDTPhotonFinderSid01 */
+    public TestPhotonFinder(String in, String outH, String outC1, String outC2)
+    {
+        inName = in;
+        outHName = outH;
+        outCName1 = outC1;
+        outCName2 = outC2;
+        clusterer = new NearestNeighborClusterer(1,1,1,0,0.);
+        hmv = new HMatrixVars();
+        add(hmv);
+        finder = new Sid01DTPhotonFinder(hmv);
+        add(new DigiPackageDriver());
+        add(new DirectedTreeDriver());
+        init = false;
+        clusternames1 = new String[2];
+    }
+    protected void process(EventHeader event)
+    {
+        if(!init)
+        {
+            init = true;
+            CalorimeterInformation ci = CalorimeterInformation.instance();
+            clusternames1[0] = ci.getDigiCollectionName(CalorimeterType.EM_BARREL)+"DTreeClusters";
+            clusternames1[1] = ci.getDigiCollectionName(CalorimeterType.EM_ENDCAP)+"DTreeClusters";
+            add(new CombineClLists(clusternames1,DTclName));
+            add(new RemoveHitsNearTracks(DTclName,"Cut"+DTclName,DTclName+"ForElectrons",outMapName));
+            add(new CoreReclusterDriver("Cut"+DTclName,ReDTclName));
+            add(new CoreReclusterDriver(DTclName+"ForElectrons",ReDTclName+"ForElectrons"));
+        }
+        super.process(event);
+        HitMap inmap = (HitMap) event.get(inName);
+        List<Cluster> inlist = event.get(Cluster.class,ReDTclName);
+        List<Cluster> sublist = new ArrayList<Cluster>();
+        Map<Cluster,Cluster> submap = new HashMap<Cluster,Cluster>();
+        for(Cluster c:inlist)
+        {
+           List<Cluster> nncl = clusterer.createClusters(c.getCalorimeterHits());
+           int maxh = 0;
+           Cluster maxc = null;
+           for(Cluster nnc:nncl)
+           {
+              if(nnc.getCalorimeterHits().size() > maxh)
+              {
+                 maxh = nnc.getCalorimeterHits().size();
+                 maxc = nnc;
+              }
+           }
+           sublist.add(maxc);
+           submap.put(maxc,c);
+        }
+        List<Cluster> subphotons = finder.findPhotons(sublist);
+        List<Cluster> photons = new ArrayList<Cluster>();
+        for(Cluster subp:subphotons)
+        {
+           BasicCluster pc = new BasicCluster();
+           for(Cluster subc:subp.getClusters())
+           {
+              pc.addCluster(submap.get(subc));
+           }
+           photons.add(pc);
+        }
+        int flag = 1<<LCIOConstants.CLBIT_HITS;
+        event.put(outCName1, photons, Cluster.class, flag );
+
+        inlist = event.get(Cluster.class,ReDTclName+"ForElectrons");
+        sublist = new ArrayList<Cluster>();
+        submap = new HashMap<Cluster,Cluster>();
+        for(Cluster c:inlist)
+        {
+           List<Cluster> nncl = clusterer.createClusters(c.getCalorimeterHits());
+           int maxh = 0;
+           Cluster maxc = null;
+           for(Cluster nnc:nncl)
+           {
+              if(nnc.getCalorimeterHits().size() > maxh)
+              {
+                 maxh = nnc.getCalorimeterHits().size();
+                 maxc = nnc;
+              }
+           }
+           sublist.add(maxc);
+           submap.put(maxc,c);
+        }
+        subphotons = finder.findPhotons(sublist);
+        List<Cluster> electrons = new ArrayList<Cluster>();
+        for(Cluster subp:subphotons)
+        {
+           BasicCluster pc = new BasicCluster();
+           for(Cluster subc:subp.getClusters())
+           {
+              pc.addCluster(submap.get(subc));
+           }
+           electrons.add(pc);
+        }
+        event.put(outCName2, electrons, Cluster.class, flag );
+
+
+        HitMap outputHitMap = new HitMap(inmap);
+//   Remove photon hits
+        for (Cluster clus : photons)
+        {
+            for (CalorimeterHit hit : clus.getCalorimeterHits())
+            {
+               Long cellID = new Long(hit.getCellID());
+               outputHitMap.remove(cellID);
+            }
+         }
+        for (Cluster clus : electrons)
+        {
+            for (CalorimeterHit hit : clus.getCalorimeterHits())
+            {
+               Long cellID = new Long(hit.getCellID());
+               outputHitMap.remove(cellID);
+            }
+         }
+         event.put(outHName, outputHitMap);
+    }
+    
+}
CVSspam 0.2.8