pfa update
diff -u -r1.2 -r1.3 --- AlternateClumpFinder.java 23 Oct 2011 09:50:28 -0000 1.2 +++ AlternateClumpFinder.java 11 Apr 2012 15:49:34 -0000 1.3 @@ -14,7 +14,7 @@
* up clusters which have multiple local maxima in energy since that may indicate * that we actually have two separate showers/clusters. *
- * @version $Id: AlternateClumpFinder.java,v 1.2 2011/10/23 09:50:28 zaidan Exp $
+ * @version $Id: AlternateClumpFinder.java,v 1.3 2012/04/11 15:49:34 zaidan Exp $
*/ public class AlternateClumpFinder extends ClumpFinder
diff -u -r1.2 -r1.3 --- ClumpFinder.java 23 Oct 2011 09:50:28 -0000 1.2 +++ ClumpFinder.java 11 Apr 2012 15:49:34 -0000 1.3 @@ -29,7 +29,7 @@
* or more for each hit. This is hard-coded at the moment, but * should become a user-definable in a later version. *
- * @version $Id: ClumpFinder.java,v 1.2 2011/10/23 09:50:28 zaidan Exp $
+ * @version $Id: ClumpFinder.java,v 1.3 2012/04/11 15:49:34 zaidan Exp $
*/ public class ClumpFinder extends Driver implements Clusterer
diff -u -r1.2 -r1.3 --- HighHitDensityDecision.java 23 Oct 2011 09:50:28 -0000 1.2 +++ HighHitDensityDecision.java 11 Apr 2012 15:49:34 -0000 1.3 @@ -14,7 +14,7 @@
* Eventually this should be made more flexible and moved outside * the "structural" package. *
- * @version $Id: HighHitDensityDecision.java,v 1.2 2011/10/23 09:50:28 zaidan Exp $
+ * @version $Id: HighHitDensityDecision.java,v 1.3 2012/04/11 15:49:34 zaidan Exp $
*/ public class HighHitDensityDecision implements DecisionMakerSingle<CalorimeterHit>
diff -u -r1.2 -r1.3 --- LocalDensityMaximumDecision.java 23 Oct 2011 09:50:28 -0000 1.2 +++ LocalDensityMaximumDecision.java 11 Apr 2012 15:49:34 -0000 1.3 @@ -12,7 +12,7 @@
* Eventually this should be made more flexible and moved outside * the "structural" package. *
- * @version $Id: LocalDensityMaximumDecision.java,v 1.2 2011/10/23 09:50:28 zaidan Exp $
+ * @version $Id: LocalDensityMaximumDecision.java,v 1.3 2012/04/11 15:49:34 zaidan Exp $
*/ public class LocalDensityMaximumDecision implements DecisionMakerSingle<CalorimeterHit>
diff -u -r1.2 -r1.3 --- ChargedNeutralFragmentSeparator.java 23 Oct 2011 09:50:28 -0000 1.2 +++ ChargedNeutralFragmentSeparator.java 11 Apr 2012 15:49:34 -0000 1.3 @@ -25,7 +25,7 @@
* A class that takes a small cluster or single hit and * tries to decide whether it is charged or neutral. *
- * @version $Id: ChargedNeutralFragmentSeparator.java,v 1.2 2011/10/23 09:50:28 zaidan Exp $
+ * @version $Id: ChargedNeutralFragmentSeparator.java,v 1.3 2012/04/11 15:49:34 zaidan Exp $
*/ public class ChargedNeutralFragmentSeparator extends Driver implements DecisionMakerSingle<Cluster>
diff -u -r1.2 -r1.3 --- CheatFragmentIdentifier.java 23 Oct 2011 09:50:29 -0000 1.2 +++ CheatFragmentIdentifier.java 11 Apr 2012 15:49:34 -0000 1.3 @@ -8,7 +8,7 @@
/** * A cheating class to determine whether a given cluster is a fragment. *
- * @version $Id: CheatFragmentIdentifier.java,v 1.2 2011/10/23 09:50:29 zaidan Exp $
+ * @version $Id: CheatFragmentIdentifier.java,v 1.3 2012/04/11 15:49:34 zaidan Exp $
*/ public class CheatFragmentIdentifier implements FragmentIdentifier {
diff -u -r1.2 -r1.3 --- CheatLikelihoodLinkDriver.java 23 Oct 2011 09:50:29 -0000 1.2 +++ CheatLikelihoodLinkDriver.java 11 Apr 2012 15:49:34 -0000 1.3 @@ -20,7 +20,7 @@
* truth information. * * @author Mat Charles <[log in to unmask]>
- * @version $Id: CheatLikelihoodLinkDriver.java,v 1.2 2011/10/23 09:50:29 zaidan Exp $
+ * @version $Id: CheatLikelihoodLinkDriver.java,v 1.3 2012/04/11 15:49:34 zaidan Exp $
*/ public class CheatLikelihoodLinkDriver extends LikelihoodLinkDriver
diff -u -r1.2 -r1.3 --- DropFragments.java 23 Oct 2011 09:50:29 -0000 1.2 +++ DropFragments.java 11 Apr 2012 15:49:34 -0000 1.3 @@ -9,7 +9,7 @@
* An implementation of <code>FragmentMerger</code>. * We simply discard every fragment. *
- * @version $Id: DropFragments.java,v 1.2 2011/10/23 09:50:29 zaidan Exp $
+ * @version $Id: DropFragments.java,v 1.3 2012/04/11 15:49:34 zaidan Exp $
*/ public class DropFragments implements FragmentMerger
diff -u -r1.2 -r1.3 --- FragmentHandler.java 23 Oct 2011 09:50:29 -0000 1.2 +++ FragmentHandler.java 11 Apr 2012 15:49:34 -0000 1.3 @@ -19,7 +19,7 @@
* * @see FragmentIdentifier * @see FragmentMerger
- * @version $Id: FragmentHandler.java,v 1.2 2011/10/23 09:50:29 zaidan Exp $
+ * @version $Id: FragmentHandler.java,v 1.3 2012/04/11 15:49:34 zaidan Exp $
*/ public class FragmentHandler extends Driver
diff -u -r1.2 -r1.3 --- FragmentIdentifier.java 23 Oct 2011 09:50:29 -0000 1.2 +++ FragmentIdentifier.java 11 Apr 2012 15:49:34 -0000 1.3 @@ -6,7 +6,7 @@
/** * Determine whether a cluster is a fragment or not. *
- * @version $Id: FragmentIdentifier.java,v 1.2 2011/10/23 09:50:29 zaidan Exp $
+ * @version $Id: FragmentIdentifier.java,v 1.3 2012/04/11 15:49:34 zaidan Exp $
*/ public interface FragmentIdentifier
diff -u -r1.2 -r1.3 --- FragmentIdentifierDecisionMaker.java 23 Oct 2011 09:50:29 -0000 1.2 +++ FragmentIdentifierDecisionMaker.java 11 Apr 2012 15:49:34 -0000 1.3 @@ -10,7 +10,7 @@
* A wrapper class that allows a FragmentIdentifier to be * treated as a DecisionMakerSingle<Cluster> *
- * @version $Id: FragmentIdentifierDecisionMaker.java,v 1.2 2011/10/23 09:50:29 zaidan Exp $
+ * @version $Id: FragmentIdentifierDecisionMaker.java,v 1.3 2012/04/11 15:49:34 zaidan Exp $
*/ public class FragmentIdentifierDecisionMaker extends Driver implements DecisionMakerSingle<Cluster>
diff -u -r1.2 -r1.3 --- FragmentMerger.java 23 Oct 2011 09:50:29 -0000 1.2 +++ FragmentMerger.java 11 Apr 2012 15:49:34 -0000 1.3 @@ -23,7 +23,7 @@
* <BR> newCluster.addCluster(fragment); // repeated for each fragment to be merged into this cluster * </BLOCKQUOTE> *
- * @version $Id: FragmentMerger.java,v 1.2 2011/10/23 09:50:29 zaidan Exp $
+ * @version $Id: FragmentMerger.java,v 1.3 2012/04/11 15:49:34 zaidan Exp $
*/ public interface FragmentMerger
diff -u -r1.2 -r1.3 --- GenericStructuralDriver.java 23 Oct 2011 09:50:29 -0000 1.2 +++ GenericStructuralDriver.java 11 Apr 2012 15:49:34 -0000 1.3 @@ -19,7 +19,7 @@
* track segments. See the process() description for more detail. * * @author Mat Charles <[log in to unmask]>
- * @version $Id: GenericStructuralDriver.java,v 1.2 2011/10/23 09:50:29 zaidan Exp $
+ * @version $Id: GenericStructuralDriver.java,v 1.3 2012/04/11 15:49:34 zaidan Exp $
*/ public abstract class GenericStructuralDriver extends Driver
diff -u -r1.2 -r1.3 --- HaloAssigner.java 23 Oct 2011 09:50:29 -0000 1.2 +++ HaloAssigner.java 11 Apr 2012 15:49:34 -0000 1.3 @@ -17,7 +17,7 @@
* Assign hits which are not part of a Cluster to a nearby Cluster. * * @author Mat Charles <[log in to unmask]>
- * @version $Id: HaloAssigner.java,v 1.2 2011/10/23 09:50:29 zaidan Exp $
+ * @version $Id: HaloAssigner.java,v 1.3 2012/04/11 15:49:34 zaidan Exp $
*/ public class HaloAssigner extends Driver
diff -u -r1.2 -r1.3 --- LikelihoodFindingStructuralDriver.java 23 Oct 2011 09:50:29 -0000 1.2 +++ LikelihoodFindingStructuralDriver.java 11 Apr 2012 15:49:34 -0000 1.3 @@ -16,7 +16,7 @@
* class must be called. * * @author Mat Charles <[log in to unmask]>
- * @version $Id: LikelihoodFindingStructuralDriver.java,v 1.2 2011/10/23 09:50:29 zaidan Exp $
+ * @version $Id: LikelihoodFindingStructuralDriver.java,v 1.3 2012/04/11 15:49:34 zaidan Exp $
*/ public class LikelihoodFindingStructuralDriver extends GenericStructuralDriver
diff -u -r1.2 -r1.3 --- LikelihoodLinkDriver.java 23 Oct 2011 09:50:29 -0000 1.2 +++ LikelihoodLinkDriver.java 11 Apr 2012 15:49:34 -0000 1.3 @@ -22,7 +22,7 @@
* LikelihoodEvaluator. * * @author Mat Charles <[log in to unmask]>
- * @version $Id: LikelihoodLinkDriver.java,v 1.2 2011/10/23 09:50:29 zaidan Exp $
+ * @version $Id: LikelihoodLinkDriver.java,v 1.3 2012/04/11 15:49:34 zaidan Exp $
*/ public class LikelihoodLinkDriver extends GenericStructuralDriver
diff -u -r1.2 -r1.3 --- LikelihoodLinkPlotDriver.java 23 Oct 2011 09:50:29 -0000 1.2 +++ LikelihoodLinkPlotDriver.java 11 Apr 2012 15:49:34 -0000 1.3 @@ -15,7 +15,7 @@
* this class makes some plots evaluating the performance. * * @author Mat Charles <[log in to unmask]>
- * @version $Id: LikelihoodLinkPlotDriver.java,v 1.2 2011/10/23 09:50:29 zaidan Exp $
+ * @version $Id: LikelihoodLinkPlotDriver.java,v 1.3 2012/04/11 15:49:34 zaidan Exp $
*/ public class LikelihoodLinkPlotDriver extends LikelihoodLinkDriver
diff -u -r1.2 -r1.3 --- Link.java 23 Oct 2011 09:50:29 -0000 1.2 +++ Link.java 11 Apr 2012 15:49:34 -0000 1.3 @@ -8,7 +8,7 @@
* org.lcsim.contrib.uiowa.uiowapfa.recon.cluster.structural * * @author Mat Charles <[log in to unmask]>
- * @version $Id: Link.java,v 1.2 2011/10/23 09:50:29 zaidan Exp $
+ * @version $Id: Link.java,v 1.3 2012/04/11 15:49:34 zaidan Exp $
*/ class Link {
diff -u -r1.2 -r1.3 --- SimpleFragmentIdentifier.java 23 Oct 2011 09:50:29 -0000 1.2 +++ SimpleFragmentIdentifier.java 11 Apr 2012 15:49:34 -0000 1.3 @@ -30,7 +30,7 @@
* the cluster being tested, it is considered to have a track and therefore * to be a primary. *
- * @version $Id: SimpleFragmentIdentifier.java,v 1.2 2011/10/23 09:50:29 zaidan Exp $
+ * @version $Id: SimpleFragmentIdentifier.java,v 1.3 2012/04/11 15:49:34 zaidan Exp $
*/ public class SimpleFragmentIdentifier implements FragmentIdentifier
diff -u -r1.2 -r1.3 --- SimpleFragmentMerger.java 23 Oct 2011 09:50:29 -0000 1.2 +++ SimpleFragmentMerger.java 11 Apr 2012 15:49:34 -0000 1.3 @@ -14,7 +14,7 @@
* can be changed by extending this class and over-riding * that method. *
- * @version $Id: SimpleFragmentMerger.java,v 1.2 2011/10/23 09:50:29 zaidan Exp $
+ * @version $Id: SimpleFragmentMerger.java,v 1.3 2012/04/11 15:49:34 zaidan Exp $
*/ public class SimpleFragmentMerger implements FragmentMerger
diff -u -r1.1 -r1.2 --- MiscUtilities.java 27 May 2011 12:01:10 -0000 1.1 +++ MiscUtilities.java 11 Apr 2012 15:49:35 -0000 1.2 @@ -15,7 +15,7 @@
import org.lcsim.util.swim.Line; import org.lcsim.recon.util.CalorimeterInformation; import org.lcsim.geometry.Calorimeter.CalorimeterType;
-import org.lcsim.recon.pfa.identifier.*;
+import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.*;
public class MiscUtilities {
diff -u -r1.2 -r1.3 --- TrackToTrackDOCA.java 23 Oct 2011 09:50:29 -0000 1.2 +++ TrackToTrackDOCA.java 11 Apr 2012 15:49:35 -0000 1.3 @@ -22,7 +22,7 @@
* four hits (otherwise the direction is not so meaningful). * * @author Mat Charles <[log in to unmask]>
- * @version $Id: TrackToTrackDOCA.java,v 1.2 2011/10/23 09:50:29 zaidan Exp $
+ * @version $Id: TrackToTrackDOCA.java,v 1.3 2012/04/11 15:49:35 zaidan Exp $
*/ public class TrackToTrackDOCA extends ClusterToClusterLikelihoodQuantity
diff -u -r1.2 -r1.3 --- TrackToTrackPOCAInCalorimeter.java 23 Oct 2011 09:50:29 -0000 1.2 +++ TrackToTrackPOCAInCalorimeter.java 11 Apr 2012 15:49:35 -0000 1.3 @@ -28,7 +28,7 @@
* at the start of every event. * * @author Mat Charles <[log in to unmask]>
- * @version $Id: TrackToTrackPOCAInCalorimeter.java,v 1.2 2011/10/23 09:50:29 zaidan Exp $
+ * @version $Id: TrackToTrackPOCAInCalorimeter.java,v 1.3 2012/04/11 15:49:35 zaidan Exp $
*/ public class TrackToTrackPOCAInCalorimeter extends ClusterToClusterLikelihoodQuantity
diff -u -r1.2 -r1.3 --- TrackToTrackSmallestDistanceToPOCA.java 23 Oct 2011 09:50:29 -0000 1.2 +++ TrackToTrackSmallestDistanceToPOCA.java 11 Apr 2012 15:49:35 -0000 1.3 @@ -25,7 +25,7 @@
* four hits (otherwise the direction is not so meaningful). * * @author Mat Charles <[log in to unmask]>
- * @version $Id: TrackToTrackSmallestDistanceToPOCA.java,v 1.2 2011/10/23 09:50:29 zaidan Exp $
+ * @version $Id: TrackToTrackSmallestDistanceToPOCA.java,v 1.3 2012/04/11 15:49:35 zaidan Exp $
*/ public class TrackToTrackSmallestDistanceToPOCA extends ClusterToClusterLikelihoodQuantity
diff -N Shower2D.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ Shower2D.java 11 Apr 2012 15:49:35 -0000 1.1 @@ -0,0 +1,36 @@
+package org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.debug; + +import java.util.*; +import hep.physics.vec.*; + +public class Shower2D +{ + protected List<ShowerBranch2D> m_branches = new Vector<ShowerBranch2D>(); + protected double m_momentum; + protected boolean m_isCharged; + protected int m_id; + + public Shower2D() + { + } + + public double getMomentum() { return m_momentum; } + public void setMomentum( double x ) { m_momentum = x; } + + public boolean isCharged() { return m_isCharged; } + public void setIsCharged( boolean b ) { m_isCharged = b; } + + public List<ShowerBranch2D> getBranches(){ return m_branches; } + public void addBranch(ShowerBranch2D branch){ + m_branches.add(branch); + branch.setMother(this); + } + + public int getId() { return m_id; } + public void setId( int i ) { m_id = i; } + + boolean m_isSpecial = false; + boolean isSpecial(){ return m_isSpecial; } + void setSpecial(boolean s){ m_isSpecial = s; } + +}
diff -N ShowerBranch2D.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ShowerBranch2D.java 11 Apr 2012 15:49:35 -0000 1.1 @@ -0,0 +1,138 @@
+package org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.debug; + +import java.util.*; + +import hep.aida.*; +import hep.physics.vec.*; +import hep.physics.particle.properties.*; + +import org.lcsim.event.CalorimeterHit; +import org.lcsim.event.Cluster; +import org.lcsim.event.MCParticle; +import org.lcsim.event.SimCalorimeterHit; +import org.lcsim.geometry.IDDecoder; +import org.lcsim.geometry.compact.Subdetector; + + + +public class ShowerBranch2D +{ + protected List<Cluster> m_listClusters = new ArrayList<Cluster>(); + protected Vector<Cluster> m_vectorClusters = new Vector<Cluster>(); + protected Map<Integer,List<Cluster>> m_mapLayerToListClusters = new HashMap<Integer,List<Cluster>>(); + protected Cluster m_lastAddedCluster; + protected Hep3Vector m_direction; + protected Hep3Vector m_position; + protected boolean m_isMip; + protected boolean m_isSeed; + protected boolean m_isPositivePole; + protected boolean m_isNegativePole; + protected boolean m_isBlock; + protected int m_id; + + protected Shower2D m_mother; + + public ShowerBranch2D() + { + } + + public void addCluster( Cluster clus ) + { + m_listClusters.add( clus ); + m_lastAddedCluster = clus; + m_vectorClusters.add( clus ); + + m_position = new BasicHep3Vector( clus.getPosition() ); + + Hep3Vector vSum = new BasicHep3Vector( 0. , 0. , 0. ); + for( int i = 0 ; i < m_vectorClusters.size() ; i++ ) + { + Hep3Vector v = null; + if( i == 0 ) v = VecOp.unit( new BasicHep3Vector( m_vectorClusters.get(i).getPosition() ) ); + else + { + v = VecOp.sub( new BasicHep3Vector( m_vectorClusters.get(i).getPosition() ) , new BasicHep3Vector( m_vectorClusters.get(i-1).getPosition() ) ); + v = VecOp.unit( v ); + } + vSum = VecOp.add( vSum , v ); + } + m_direction = VecOp.mult( m_vectorClusters.size() , vSum ); + } + + public Cluster getLastAddedCluster() + { + return m_lastAddedCluster; + } + + public List<Cluster> getClusters() + { + return m_listClusters; + } + + public List<Cluster> getListClusterOnLayer( Integer ii ) + { + return m_mapLayerToListClusters.get( ii ); + } + + public void setLayerAndCluster( Integer ii , Cluster clus2D ) + { + Set<Integer> setLayer = m_mapLayerToListClusters.keySet(); + List<Integer> listLayer = new ArrayList<Integer>( setLayer ); + if( listLayer.contains( ii ) ) + { + List<Cluster> listClus2D = m_mapLayerToListClusters.get( ii ); + listClus2D.add( clus2D ); + } + else + { + List<Cluster> listClus2D = new ArrayList<Cluster>(); + listClus2D.add( clus2D ); + m_mapLayerToListClusters.put( ii , listClus2D ); + } + } + + public int getSize() + { + return m_listClusters.size(); + } + + public double getEnergy() + { + double e = 0.; + for( Cluster clus : m_listClusters ) e += clus.getEnergy(); + return e; + } + + + public Hep3Vector getDirection() { return m_direction; } + public void setDirection( Hep3Vector v ) { m_direction = v; } + + public Hep3Vector getPosition() { return m_position; } + public void setPosition( Hep3Vector v ) { m_position = v; } + + public double getMomentum() { return m_mother.getMomentum(); } + + public boolean isCharged() { return m_mother.isCharged(); } + + public boolean isMip() { return m_isMip; } + public void setIsMip( boolean b ) { m_isMip = b; } + + public boolean isSeed() { return m_isSeed; } + public void setIsSeed( boolean b ) { m_isSeed = b; } + + public boolean isPositivePole() { return m_isPositivePole; } + public void setIsPositivePole( boolean b ) { m_isPositivePole = b; } + + public boolean isNegativePole() { return m_isNegativePole; } + public void setIsNegativePole( boolean b ) { m_isNegativePole = b; } + + public boolean isBlock() { return m_isBlock; } + public void setIsBlock( boolean b ) { m_isBlock = b; } + + public int getId() { return m_id; } + public void setId( int i ) { m_id = i; } + + public Shower2D getMother(){ return m_mother; } + public void setMother(Shower2D mother){ m_mother = mother; } + +}
diff -u -r1.1 -r1.2 --- DebugParticles.java 23 Oct 2011 09:50:30 -0000 1.1 +++ DebugParticles.java 11 Apr 2012 15:49:35 -0000 1.2 @@ -5,7 +5,7 @@
import org.lcsim.event.*; import org.lcsim.recon.cluster.util.*; import org.lcsim.util.hitmap.*;
-import org.lcsim.recon.pfa.identifier.*;
+import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.*;
import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.structural.shower.*; import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.structural.sharing.*; import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.structural.*;
diff -u -r1.1 -r1.2 --- DebugPhotonDriver.java 23 Oct 2011 09:50:30 -0000 1.1 +++ DebugPhotonDriver.java 11 Apr 2012 15:49:35 -0000 1.2 @@ -1,6 +1,6 @@
package org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.debug;
-import org.lcsim.recon.pfa.identifier.*;
+import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.*;
import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.structural.*; import java.util.*; import java.io.IOException;
diff -u -r1.1 -r1.2 --- DebugRegionalEoverP.java 23 Oct 2011 09:50:30 -0000 1.1 +++ DebugRegionalEoverP.java 11 Apr 2012 15:49:35 -0000 1.2 @@ -4,11 +4,13 @@
import hep.physics.vec.*; import hep.physics.particle.properties.*; import org.lcsim.event.*;
+import org.lcsim.recon.util.CalorimeterInformation; +import org.lcsim.geometry.Calorimeter.CalorimeterType;
import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.structural.*; import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.structural.shower.*; import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.structural.sharing.*; import org.lcsim.recon.cluster.util.*;
-import org.lcsim.recon.pfa.identifier.*;
+import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.*;
public class DebugRegionalEoverP {
@@ -75,7 +77,9 @@
tree.addBranch("energyFromMomentumTrueType", "D"); tree.addBranch("energyFromMomentumUncertainty", "D"); tree.addBranch("energyFromCharged", "D");
+ tree.addBranch("energyFromChargedInEcal", "D");
tree.addBranch("energyFromNeutral", "D");
+ tree.addBranch("energyFromNeutralInEcal", "D");
tree.addBranch("energyShared", "D"); tree.addBranch("energyTotal", "D"); tree.addBranch("energyFromTrueNeutral", "D");
@@ -113,6 +117,7 @@
int eventUID = m_bookKeeper.getEvent().hashCode();
+ boolean isEventOK = true;
for(Set<Shower> showerGroup : showerGroups){ int showerGroupSize = showerGroup.size();
@@ -125,7 +130,9 @@
double energyFromTrueMomentum = 0; double energyFromMomentumTrueType = 0; Set<Cluster> clustersFromCharged = new HashSet<Cluster>();
+ Set<Cluster> clustersFromChargedInEcal = new HashSet<Cluster>();
Set<Cluster> clustersFromNeutral = new HashSet<Cluster>();
+ Set<Cluster> clustersFromNeutralInEcal = new HashSet<Cluster>();
Set<Cluster> clustersShared = new HashSet<Cluster>(); Set<Cluster> clustersAll = new HashSet<Cluster>(); Set<Track> tracksAll = new HashSet<Track>();
@@ -143,9 +150,31 @@
energyFromMomentumTrueType = Math.sqrt(momentum*momentum + trueMass*trueMass); clustersFromCharged.addAll(shower.getShowerComponents()); tracksAll.addAll(shower.getTracks());
+ for(Cluster clus : shower.getShowerComponents()){ + for(CalorimeterHit hit : clus.getCalorimeterHits()){ + String detName = hit.getSubdetector().getName(); + CalorimeterInformation ci = CalorimeterInformation.instance(); + if(detName.equals(ci.getName(CalorimeterType.EM_BARREL)) || + detName.equals(ci.getName(CalorimeterType.EM_ENDCAP)) ){ + clustersFromChargedInEcal.add(clus); + } + break; + } + }
} if(shower.isNeutral()){ clustersFromNeutral.addAll(shower.getShowerComponents());
+ for(Cluster clus : shower.getShowerComponents()){ + for(CalorimeterHit hit : clus.getCalorimeterHits()){ + String detName = hit.getSubdetector().getName(); + CalorimeterInformation ci = CalorimeterInformation.instance(); + if(detName.equals(ci.getName(CalorimeterType.EM_BARREL)) || + detName.equals(ci.getName(CalorimeterType.EM_ENDCAP)) ){ + clustersFromNeutralInEcal.add(clus); + } + break; + } + }
} } double energyFromMomentumUncertainty = PFAUtil.estimatedEnergyUncertainty(tracksAll, m_bookKeeper.getEvent());
@@ -154,7 +183,9 @@
clustersAll.addAll(clustersFromCharged); clustersAll.addAll(clustersFromNeutral); double energyFromCharged = PFAUtil.energy(clustersFromCharged, allSharedClusters, calib);
+ double energyFromChargedInEcal = PFAUtil.energy(clustersFromChargedInEcal, allSharedClusters, calib);
double energyFromNeutral = PFAUtil.energy(clustersFromNeutral, allSharedClusters, calib);
+ double energyFromNeutralInEcal = PFAUtil.energy(clustersFromNeutralInEcal, allSharedClusters, calib);
double energyShared = PFAUtil.energy(clustersShared, allSharedClusters, calib); double energyTotal = PFAUtil.energy(clustersAll, allSharedClusters, calib);
@@ -228,6 +259,10 @@
} }
+ if(Math.abs(energyFromCharged - energyFromMomentum) / energyFromMomentumUncertainty > 3){ + isEventOK = false; + } +
tree.setBranchValue("eventUID", eventUID); tree.setBranchValue("showerGroupSize", showerGroupSize); tree.setBranchValue("showerGroupNCharged", showerGroupNCharged);
@@ -236,7 +271,9 @@
tree.setBranchValue("energyFromMomentumTrueType", energyFromMomentumTrueType); tree.setBranchValue("energyFromMomentumUncertainty", energyFromMomentumUncertainty); tree.setBranchValue("energyFromCharged", energyFromCharged);
+ tree.setBranchValue("energyFromChargedInEcal", energyFromChargedInEcal);
tree.setBranchValue("energyFromNeutral", energyFromNeutral);
+ tree.setBranchValue("energyFromNeutralInEcal", energyFromNeutralInEcal);
tree.setBranchValue("energyShared", energyShared); tree.setBranchValue("energyTotal", energyTotal); tree.setBranchValue("energyFromTrueNeutral", energyFromTrueNeutral);
@@ -252,6 +289,8 @@
tree.fill(); }
+ + m_bookKeeper.getEvent().put("isEventOK_"+treeName, new Boolean(isEventOK));
} protected Map<Shower, Set<Shower>> groupNearbyShowers(ShowerContainer showerContainer, double angleForGrouping){
diff -u -r1.1 -r1.2 --- DebugShowersDriver.java 23 Oct 2011 09:50:30 -0000 1.1 +++ DebugShowersDriver.java 11 Apr 2012 15:49:35 -0000 1.2 @@ -15,7 +15,8 @@
import org.lcsim.recon.cluster.mipfinder.*; import org.lcsim.recon.cluster.util.*; import org.lcsim.contrib.uiowa.uiowapfa.recon.cluster.clumpfinder.*;
-import org.lcsim.recon.pfa.identifier.*;
+import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.structural.*; +import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.*;
import org.lcsim.mc.fast.tracking.ReconTrack; import org.lcsim.event.base.*; import hep.physics.particle.Particle;
@@ -23,17 +24,22 @@
import org.lcsim.contrib.uiowa.uiowapfa.recon.cluster.structural.*; import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.structural.sharing.*; import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.structural.shower.*;
-import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.structural.*;
import org.lcsim.util.aida.*; import org.lcsim.recon.util.CalorimeterInformation; import org.lcsim.geometry.Calorimeter.CalorimeterType; import org.lcsim.geometry.*; import org.lcsim.util.swim.HelixSwimmer;
+import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.*;
+import org.lcsim.recon.cluster.*; +import org.lcsim.contrib.uiowa.uiowapfa.recon.cluster.clumpfinder.kmean.*;
public class DebugShowersDriver extends Driver {
+ protected DebugUtils m_debugUtils; + protected LinkQualityChecker m_LQChecker; +
protected EventHeader m_event = null; protected DebugUtils m_hitBasedDebugUtils = null; protected DebugUtils m_energyBasedDebugUtils = null;
@@ -95,6 +101,10 @@
//
+ protected IHistogram1D m_h_score , m_h_score_energyWeighted; + + // +
protected IHistogram2D m_h3_bin0_showerNumClusVsPurity_photon; protected IHistogram2D m_h3_bin0_showerPosition_photon , m_h3_bin0_position_photon; protected IHistogram2D m_h3_bin0_showerAngleDistance_photon , m_h3_bin0_angleDistance_photon;
@@ -177,6 +187,10 @@
///////// TTree m_showerDebugTree; TTree m_showerLinksTree;
+ TTree m_clusterDebugTree; + TTree m_layerDebugTree; + TTree m_shower2DDebugTree; + TTree m_clus2DDebugTree;
///////// public DebugShowersDriver( PFABookKeepingBroker bookKeeper, HelixExtrapolator extrapolator ){
@@ -189,6 +203,14 @@
public DebugShowersDriver( PFABookKeepingBroker bookKeeper, HelixExtrapolator extrapolator , String mcListName, String EcalDigiHitMapName, String HcalDigiHitMapName){
+ m_debugUtils = new DebugUtils(); + m_debugUtils.setMCListName( mcListName ); + m_debugUtils.setEcalDigiHitMapName( EcalDigiHitMapName ); + m_debugUtils.setHcalDigiHitMapName( HcalDigiHitMapName ); + m_debugUtils.setEnergyBased( true ); + + m_LQChecker = new DominantParticleBasedLQChecker( m_debugUtils ); +
m_hitBasedDebugUtils = new DebugUtils(); m_hitBasedDebugUtils.setMCListName(mcListName); m_hitBasedDebugUtils.setEcalDigiHitMapName(EcalDigiHitMapName);
@@ -390,6 +412,10 @@
m_h_combinedEResidual_angle = m_histoFactory.createHistogram2D("combinedEResidual_angle", 100, 0, Math.PI, 100, -10, 10);
+ m_h_score = m_histoFactory.createHistogram1D( "score" , 200 , 0.6 , 1.1 ); + m_h_score_energyWeighted = m_histoFactory.createHistogram1D( "score_energyWeighted" , 200 , 0.6 , 1.1 ); + +
for(int iShowerType=0; iShowerType<m_nShowerTypes; iShowerType++){ String showerType = m_showerTypes[iShowerType]; m_tree.mkdir(showerType);
@@ -447,7 +473,6 @@
} m_showerDebugTree = new TTree(m_outputFileName+".tree");
-
m_showerDebugTree.addBranch("size", "I"); m_showerDebugTree.addBranch("isRecoNeutral", "B"); m_showerDebugTree.addBranch("energy", "D");
@@ -512,7 +537,6 @@
m_showerDebugTree.addBranch( "primaryLikelihood" , "D" ); m_showerLinksTree = new TTree(m_outputFileName+".links.tree");
-
m_showerLinksTree.addBranch("eventUID", "I"); m_showerLinksTree.addBranch("baseID", "I"); m_showerLinksTree.addBranch("baseSize", "I");
@@ -561,161 +585,1820 @@
m_showerLinksTree.addBranch("baseToTargetLikelihoodNeutral", "D"); m_showerLinksTree.addBranch( "baseCorePurity" , "D" ); m_showerLinksTree.addBranch( "targetCorePurity" , "D" );
+ + m_clusterDebugTree = new TTree(m_outputFileName+".clusterDebug.tree"); + m_clusterDebugTree.addBranch( "clusLayerPos" , "I" ); + m_clusterDebugTree.addBranch( "clusLayerNeg" , "I" ); + m_clusterDebugTree.addBranch( "clusDistPos" , "D" ); + m_clusterDebugTree.addBranch( "clusDistNeg" , "D" ); + m_clusterDebugTree.addBranch( "clusPosX" , "D" ); + m_clusterDebugTree.addBranch( "clusPosY" , "D" ); + m_clusterDebugTree.addBranch( "clusPosZ" , "D" ); + m_clusterDebugTree.addBranch( "clusNegX" , "D" ); + m_clusterDebugTree.addBranch( "clusNegY" , "D" ); + m_clusterDebugTree.addBranch( "clusNegZ" , "D" ); + m_clusterDebugTree.addBranch( "clusCenterX" , "D" ); + m_clusterDebugTree.addBranch( "clusCenterY" , "D" ); + m_clusterDebugTree.addBranch( "clusCenterZ" , "D" ); + m_clusterDebugTree.addBranch( "clusEnergy" , "D" ); + m_clusterDebugTree.addBranch( "clusPhoton" , "B" ); + m_clusterDebugTree.addBranch( "clusGood" , "B" ); + m_clusterDebugTree.addBranch( "clusReco" , "B" ); + + m_layerDebugTree = new TTree( m_outputFileName + ".layerDebug.tree" ); + m_layerDebugTree.addBranch( "hitLayer" , "I" ); + m_layerDebugTree.addBranch( "hitTrueHit" , "I" ); + m_layerDebugTree.addBranch( "hitTrueClus" , "I" ); + m_layerDebugTree.addBranch( "hitReco" , "I" ); + m_layerDebugTree.addBranch( "hitRecoShower" , "I" ); + m_layerDebugTree.addBranch( "hitClusIsPhoton" , "B" ); + //m_layerDebugTree.addBranch( "hitRawEnergy" , "D" ); + m_layerDebugTree.addBranch( "hitCorrectedEnergy" , "D" ); + //m_layerDebugTree.addBranch( "hitTime" , "D" ); + m_layerDebugTree.addBranch( "hitX" , "D" ); + m_layerDebugTree.addBranch( "hitY" , "D" ); + m_layerDebugTree.addBranch( "hitZ" , "D" ); + m_layerDebugTree.addBranch( "hitSeed" , "B" ); + m_layerDebugTree.addBranch( "hitMip" , "B" ); + + m_shower2DDebugTree = new TTree( m_outputFileName + ".shower2DDebug.tree" ); + m_shower2DDebugTree.addBranch( "shower2DPurity" , "D" ); + m_shower2DDebugTree.addBranch( "shower2DEfficiency" , "D" ); + + m_clus2DDebugTree = new TTree( m_outputFileName + ".clus2DDebug.tree" ); + m_clus2DDebugTree.addBranch( "clus2DNumberOfHits" , "I" ); + m_clus2DDebugTree.addBranch( "clus2DLayerNumber" , "I" ); + m_clus2DDebugTree.addBranch( "clus2DPurity" , "D" ); + m_clus2DDebugTree.addBranch( "clus2DEnergy" , "D" ); + m_clus2DDebugTree.addBranch( "clus2DIsPhoton" , "B" ); + m_clus2DDebugTree.addBranch( "clus2DIsMip" , "B" ); + m_clus2DDebugTree.addBranch( "clus2DShowerTruthID" , "I" ); + m_clus2DDebugTree.addBranch( "clus2DShowerID" , "I" ); + m_clus2DDebugTree.addBranch( "clus2DBranchID" , "I" ); + m_clus2DDebugTree.addBranch( "clus2DX" , "D" ); + m_clus2DDebugTree.addBranch( "clus2DY" , "D" ); + m_clus2DDebugTree.addBranch( "clus2DZ" , "D" ); + + } + + public void process(EventHeader event){ + init(); + + m_event = event; + + m_debugUtils.setEventInfo(event); + m_hitBasedDebugUtils.setEventInfo(event); + m_energyBasedDebugUtils.setEventInfo(event); + + List<StructuralLikelihoodQuantity> vQuantity = m_showerToShowerEval.getLikelihoodQuantities() ; + + for(StructuralLikelihoodQuantity iQuantity : vQuantity) { + if(!(iQuantity instanceof ShowerToShowerLikelihoodQuantity)){ + throw new AssertionError("Quantity "+iQuantity.getClass().getName()+" does not inherit from ShowerToShowerLikelihoodQuantity"); + } + ShowerToShowerLikelihoodQuantity iShowerQuantity = (ShowerToShowerLikelihoodQuantity)iQuantity; + iShowerQuantity.setEventInfo(m_event); + iShowerQuantity.setBookKeepingBroker(m_bookKeeper); + } + + vQuantity = m_primaryShowerEval.getLikelihoodQuantities() ; + + for(StructuralLikelihoodQuantity iQuantity : vQuantity) { + if(!(iQuantity instanceof ShowerToShowerLikelihoodQuantity)){ + throw new AssertionError("Quantity "+iQuantity.getClass().getName()+" does not inherit from ShowerToShowerLikelihoodQuantity"); + } + ShowerToShowerLikelihoodQuantity iShowerQuantity = (ShowerToShowerLikelihoodQuantity)iQuantity; + iShowerQuantity.setEventInfo(m_event); + iShowerQuantity.setBookKeepingBroker(m_bookKeeper); + } + + super.process(m_event); + + m_eventCount++; + if (m_doCheckpoints && m_eventCount % 50 == 0) { + // Checkpoint + commit(); + }
}
- public void process(EventHeader event){ - init();
+ public void doAnalysis(ShowerContainer showerContainer, + Collection<Cluster> clusters, + List<SharedClusterGroup> allSharedClusters) { + + Variables vars = new Variables(); + Set<Shower> showers = showerContainer.getShowers(); + for (Shower shower : showers) { + if( shower.isNeutral() ) + { + continue; + } + Set<Track> tracks = shower.getTracks(); + Set<Cluster> showerComponents = shower.getShowerComponents(); + vars.showerSize = shower.size(); + vars.clusterEnergy = shower.realEnergy(); + vars.trackMomentum = shower.scalarMomentum(); + double sigma = shower.estimatedEnergyUncertainty(); + vars.normalizedResidual = (vars.clusterEnergy-vars.trackMomentum)/sigma; + vars.hitBasedEfficiency = m_hitBasedDebugUtils.quoteEfficiency_T(tracks, showerComponents, allSharedClusters); + vars.hitBasedPurity = m_hitBasedDebugUtils.quotePurity_T(tracks, showerComponents, allSharedClusters); + vars.hitBasedCoreEfficiency = m_hitBasedDebugUtils.quoteEfficiency_T(tracks, showerComponents); + vars.hitBasedCorePurity = m_hitBasedDebugUtils.quotePurity_T(tracks, showerComponents); + vars.energyBasedEfficiency = m_energyBasedDebugUtils.quoteEfficiency_T(tracks, showerComponents, allSharedClusters); + vars.energyBasedPurity = m_energyBasedDebugUtils.quotePurity_T(tracks, showerComponents, allSharedClusters); + vars.energyBasedCoreEfficiency = m_energyBasedDebugUtils.quoteEfficiency_T(tracks, showerComponents); + vars.energyBasedCorePurity = m_energyBasedDebugUtils.quotePurity_T(tracks, showerComponents); + boolean isPunchThrough = false; + if(m_checkSharedHitsForPunchThrough){ + isPunchThrough = m_punchThroughCheck.isPunchThrough(shower, m_event, allSharedClusters); + }else{ + isPunchThrough = m_punchThroughCheck.isPunchThrough(shower, m_event); + } + if(shower.isJet()) { + if(isPunchThrough){ + fillHistograms("PunchThroughJets", vars); + }else{ + fillHistograms("Jets", vars); + } + }else{ + if(isPunchThrough){ + fillHistograms("PunchThroughTracks", vars); + }else{ + fillHistograms("Tracks", vars); + } + } + } + + List<Shower> showerList = new Vector<Shower>(); + showerList.addAll(showerContainer.getShowers()); + for(int i=0; i<showerList.size(); i++){ + Shower shower1 = showerList.get(i); + if(shower1.isNeutral()) continue; + Hep3Vector p1 = shower1.momentum(); + double energy1 = shower1.realEnergy(); + double sigma1 = shower1.estimatedEnergyUncertainty(); + Set<Cluster> clusters1 = shower1.getShowerComponents(); + ClusterEnergyCalculator calib = shower1.getEnergyCalculator(); + for(int j=i+1; j<showerList.size(); j++){ + Shower shower2 = showerList.get(j); + if(shower2.isNeutral()) continue; + Hep3Vector p2 = shower2.momentum(); + double energy2 = shower2.realEnergy(); + double sigma2 = shower2.estimatedEnergyUncertainty(); + Set<Cluster> clusters2 = shower2.getShowerComponents(); + + Set<Cluster> combinedShowerComponents = new HashSet<Cluster>(); + combinedShowerComponents.addAll(clusters1); + combinedShowerComponents.addAll(clusters2); + Shower combinedShower = ShowerFactory.createShower(calib, allSharedClusters, combinedShowerComponents); + + double angle = Math.acos(VecOp.dot(VecOp.unit(p1), VecOp.unit(p2))); + double sumE = energy1 + energy2; + double combinedE = combinedShower.realEnergy(); + double commonE = sumE - combinedE; + double combinedP = VecOp.add(p1, p2).magnitude(); + double combinedSigma = Math.sqrt(sigma1*sigma1 + sigma2*sigma2); + + if(sumE == 0){ throw new AssertionError("Energy sum is zer!!!"); } + if(combinedP == 0){ throw new AssertionError("Combined momentum is zero!!!"); } + if(combinedSigma == 0){ throw new AssertionError("Combined sigma is zero!!!"); } + + m_h_sharedEnergyFranction_angle.fill(angle, commonE/combinedE); + m_h_sumEOverP_angle.fill(angle, sumE/combinedP); + m_h_combinedEOverP_angle.fill(angle, combinedE/combinedP); + m_h_sumEResidual_angle.fill(angle, (sumE - combinedP)/combinedSigma); + m_h_combinedEResidual_angle.fill(angle, (combinedE - combinedP)/combinedSigma); + } + } + + Vector<Hep3Vector> trackDirection = new Vector<Hep3Vector>(); + Vector<Hep3Vector> trackPosition = new Vector<Hep3Vector>(); + + for( Shower shower : showerContainer.getShowers() ) + { + if( shower.isNeutral() ) continue; + + Track track = null; + Cluster seed = null; + Set<Track> tracks = shower.getTracks(); + for( Track trk : tracks ) + { + track = trk; + seed = shower.getSeed( track ); + break; + } + + Hep3Vector [] directionPosition = PFAUtil.getTrackExtrapolation( track , seed , 0 , m_extrapolator ); + + Hep3Vector directionTrack = directionPosition[0]; + Hep3Vector positionTrack = directionPosition[1]; + + trackDirection.add( directionTrack ); + trackPosition.add( positionTrack ); + } + + + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + + + // 2D : gammaphi + + m_layerDebugTree.setBranchValue( "hitLayer" , 1111 ); + m_layerDebugTree.setBranchValue( "hitTrueHit" , 0 ); + m_layerDebugTree.setBranchValue( "hitTrueClus" , 0 ); + m_layerDebugTree.setBranchValue( "hitReco" , 0 ); + m_layerDebugTree.setBranchValue( "hitRecoShower" , 0 ); + m_layerDebugTree.setBranchValue( "hitClusIsPhoton" , false ); + //m_layerDebugTree.setBranchValue( "hitRawEnergy" , 0. ); + m_layerDebugTree.setBranchValue( "hitCorrectedEnergy" , 0. ); + //m_layerDebugTree.setBranchValue( "hitTime" , 0. ); + m_layerDebugTree.setBranchValue( "hitX" , 0. ); + m_layerDebugTree.setBranchValue( "hitY" , 0. ); + m_layerDebugTree.setBranchValue( "hitZ" , 0. ); + m_layerDebugTree.setBranchValue( "hitSeed" , false ); + m_layerDebugTree.setBranchValue( "hitMip" , false ); + m_layerDebugTree.fill(); + + m_clus2DDebugTree.setBranchValue( "clus2DNumberOfHits" , 0 ); + m_clus2DDebugTree.setBranchValue( "clus2DLayerNumber" , 1111 ); + m_clus2DDebugTree.setBranchValue( "clus2DPurity" , 0. ); + m_clus2DDebugTree.setBranchValue( "clus2DEnergy" , 0. ); + m_clus2DDebugTree.setBranchValue( "clus2DIsPhoton" , false ); + m_clus2DDebugTree.setBranchValue( "clus2DIsMip" , false ); + m_clus2DDebugTree.setBranchValue( "clus2DShowerTruthID" , 0 ); + m_clus2DDebugTree.setBranchValue( "clus2DShowerID" , 0 ); + m_clus2DDebugTree.setBranchValue( "clus2DBranchID" , 0 ); + m_clus2DDebugTree.setBranchValue( "clus2DX" , 0. ); + m_clus2DDebugTree.setBranchValue( "clus2DY" , 0. ); + m_clus2DDebugTree.setBranchValue( "clus2DZ" , 0. ); + m_clus2DDebugTree.fill(); + + + /* + for( Shower shower : showerContainer.getShowers() ) + { + if( shower.getTracks() == null ) continue; + + for( Track trk : shower.getTracks() ) + { + for( int ilayer = 0 ; ilayer < 31 ; ilayer++ ) + { + if( trk instanceof MultipleTrackTrack ) // FixMe!!! in case the direction of the tracks are so different. + { + for( Track subTrack : trk.getTracks() ) + { + HelixExtrapolationResult result = m_extrapolator.performExtrapolation( subTrack ); + if( result == null ) { System.out.println( "> + > + > Extrapolatin of the subTrack failed." ); continue; } + + Hep3Vector positionOfTrack = result.extendToECALEndcapLayer( ilayer ); + if( positionOfTrack == null ) positionOfTrack = result.extendToECALBarrelLayer( ilayer ); + + if( positionOfTrack == null ) { System.out.println( "> + > + > Extrapolatin of the subTrack failed 2." ); continue; } + + m_clus2DDebugTree.setBranchValue( "clus2DNumberOfHits" , 0 ); + m_clus2DDebugTree.setBranchValue( "clus2DLayerNumber" , ilayer ); + m_clus2DDebugTree.setBranchValue( "clus2DPurity" , 0. ); + m_clus2DDebugTree.setBranchValue( "clus2DEnergy" , new BasicHep3Vector( subTrack.getMomentum() ).magnitude() ); + m_clus2DDebugTree.setBranchValue( "clus2DIsPhoton" , false ); + m_clus2DDebugTree.setBranchValue( "clus2DIsMip" , true ); + m_clus2DDebugTree.setBranchValue( "clus2DShowerTruthID" , 0 ); + m_clus2DDebugTree.setBranchValue( "clus2DShowerID" , 0 ); + m_clus2DDebugTree.setBranchValue( "clus2DBranchID" , 0 ); + m_clus2DDebugTree.setBranchValue( "clus2DX" , positionOfTrack.x() ); + m_clus2DDebugTree.setBranchValue( "clus2DY" , positionOfTrack.y() ); + m_clus2DDebugTree.setBranchValue( "clus2DZ" , positionOfTrack.z() ); + m_clus2DDebugTree.fill(); + + } + + } + else + { + HelixExtrapolationResult result = m_extrapolator.performExtrapolation( trk ); + if( result == null ) { System.out.println( "> + > + > Extrapolatin of the subTrack failed." ); continue; } + + Hep3Vector positionOfTrack = result.extendToECALEndcapLayer( ilayer ); + if( positionOfTrack == null ) positionOfTrack = result.extendToECALBarrelLayer( ilayer ); + + if( positionOfTrack == null ) { System.out.println( "> + > + > Extrapolatin of the subTrack failed 2." ); continue; } + + m_clus2DDebugTree.setBranchValue( "clus2DNumberOfHits" , 0 ); + m_clus2DDebugTree.setBranchValue( "clus2DLayerNumber" , ilayer ); + m_clus2DDebugTree.setBranchValue( "clus2DPurity" , 0. ); + m_clus2DDebugTree.setBranchValue( "clus2DEnergy" , new BasicHep3Vector( trk.getMomentum() ).magnitude() ); + m_clus2DDebugTree.setBranchValue( "clus2DIsPhoton" , false ); + m_clus2DDebugTree.setBranchValue( "clus2DIsMip" , false ); + m_clus2DDebugTree.setBranchValue( "clus2DShowerTruthID" , 0 ); + m_clus2DDebugTree.setBranchValue( "clus2DShowerID" , 0 ); + m_clus2DDebugTree.setBranchValue( "clus2DBranchID" , 0 ); + m_clus2DDebugTree.setBranchValue( "clus2DX" , positionOfTrack.x() ); + m_clus2DDebugTree.setBranchValue( "clus2DY" , positionOfTrack.y() ); + m_clus2DDebugTree.setBranchValue( "clus2DZ" , positionOfTrack.z() ); + m_clus2DDebugTree.fill(); + } + + } + } + } + */ + + + Collection<Cluster> photons = m_bookKeeper.getClusterList( "Photons" ); + Collection<Cluster> mips = m_bookKeeper.getClusterList( "Mips" ); + Collection<Cluster> clumps = m_bookKeeper.getClusterList( "Clumps" ); + Collection<Cluster> blocks = m_bookKeeper.getClusterList( "Blocks" ); + Collection<Cluster> leftoverHitClusters = m_bookKeeper.getClusterList( "Leftovers" ); + + // Map to tag the showers by used in the group of showers or not. The aim is to avoid the use of the shower more than one time. + Map<Shower,Boolean> mapShowerToIsUsed = new HashMap<Shower,Boolean>(); + for( Shower shower : showerContainer.getShowers() ) mapShowerToIsUsed.put( shower , new Boolean(false) ); + + // This is the grouping angle of the shower + double angleForGrouping = 60. * Math.PI / 180.; + Map<Shower,Set<Shower>> mapShowerToSetShowers = groupShowers( showerContainer , angleForGrouping ); + + + // begin check ///////////////////////////////////////////////////////////////////////////////////////////////////////////// + + Map<CalorimeterHit,Integer> mapHitToRecoShower2D = new HashMap<CalorimeterHit,Integer>(); + int iRecoShower2D = 0; + + for( Shower shower : showerContainer.getShowers() ) + { + // check if the shower is in the shower container + List<Shower> tempListShower = new ArrayList<Shower>( mapShowerToSetShowers.get( shower ) ); + if( !tempListShower.contains ( shower ) ) System.out.println( "Error!!! In DebugShowersDriver.java No. 348234234" ); + + // + + // shower purity + Cluster showerCore_ = PFAUtil.makeCombinedCluster( shower.getShowerComponents() ); + double shower2DPurity = m_debugUtils.quotePurity( showerCore_ ); + + // shower efficiency + MCParticle domPart1 = m_debugUtils.quoteDominantParticle( showerCore_ ); + double shower2DEfficiency = m_debugUtils.quoteEfficiency_P( domPart1 , showerCore_ ); + + m_shower2DDebugTree.setBranchValue( "shower2DPurity" , shower2DPurity ); + m_shower2DDebugTree.setBranchValue( "shower2DEfficiency" , shower2DEfficiency ); + //m_shower2DDebugTree.fill(); + + // + + // fill mapHitToRecoShower2D + iRecoShower2D++; + for( Cluster clus : shower.getShowerComponents() ) + for( CalorimeterHit hit : clus.getCalorimeterHits() ) + mapHitToRecoShower2D.put( hit , new Integer( iRecoShower2D ) ); + } + + // end check /////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + + // Definition of the K-Mean cluster finder + KMeanClumpFinder clus2DFinder = new KMeanClumpFinder(); + + // Seed finding + int SDT333 = 0; + int SDT553 = 0; + int SST = 1; + + // Clump finding + int CDT333 = 0; + int CDT553 = 0; + int CST = 1; + int maxItr = 1; + + KMeanParameters kMeanParameters = new KMeanParameters( SDT333 , SDT553 , SST , CDT333 , CDT553 , CST , maxItr ); + clus2DFinder.setParameters( kMeanParameters ); + + // Number of the calorimeter layers + int totalNumberOfLayers = 71; + + + + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + + + // For loop on the group of showers + for( Shower showerMother : showerContainer.getShowers() ) + { + // checking if it is used + boolean isUsed = mapShowerToIsUsed.get( showerMother ).booleanValue(); + if( isUsed ) continue; + + System.out.println( ">>>>>>>>>>>>>>> new group of showers" ); + + // tag the MC particle by a number + Map<MCParticle,Integer> mapMCtoInt = new HashMap<MCParticle,Integer>(); + int iMCtoInt = 0; + + // shower id + int iShowerId = 1; + int iBranchId = 1; + + // seed mip clump 3D //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + List<Cluster> listSeedMip3D = new ArrayList<Cluster>(); + List<Cluster> listSeedClump3D = new ArrayList<Cluster>(); + List<Cluster> listNoSeedMip3D = new ArrayList<Cluster>(); + List<Cluster> listNoSeedClump3D = new ArrayList<Cluster>(); + for( Shower shower : mapShowerToSetShowers.get( showerMother ) ) + for( Cluster clus : shower.getSeeds() ) + { + //if( !listSeedMip3D.contains( clus ) && mips.contains( clus ) ) listSeedMip3D.add( clus ); + //if( !listSeedClump3D.contains( clus ) && ( clumps.contains( clus ) || ( blocks.contains( clus ) ) ) ) listSeedClump3D.add( clus ); + } + for( Shower shower : mapShowerToSetShowers.get( showerMother ) ) + for( Cluster clus : shower.getShowerComponents() ) + { + //if( !listNoSeedMip3D.contains( clus ) && !listSeedMip3D.contains(clus) && mips.contains( clus ) ) listNoSeedMip3D.add( clus ); + //if( !listNoSeedClump3D.contains( clus ) && !listSeedClump3D.contains( clus ) && ( clumps.contains( clus ) || blocks.contains( clus ) ) ) listNoSeedClump3D.add( clus ); + if( !listNoSeedClump3D.contains( clus ) ) listNoSeedClump3D.add( clus ); + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + + // map layer to seed mip clump 3D /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + Map<Integer,Set<CalorimeterHit>> mapLayerToSetSeedMip3DHits = new HashMap<Integer,Set<CalorimeterHit>>(); + Map<Integer,Set<CalorimeterHit>> mapLayerToSetSeedClump3DHits = new HashMap<Integer,Set<CalorimeterHit>>(); + Map<Integer,Set<CalorimeterHit>> mapLayerToSetNoSeedMip3DHits = new HashMap<Integer,Set<CalorimeterHit>>(); + Map<Integer,Set<CalorimeterHit>> mapLayerToSetNoSeedClump3DHits = new HashMap<Integer,Set<CalorimeterHit>>(); + for( int i = 0 ; i < totalNumberOfLayers ; i++ ) + { + mapLayerToSetSeedMip3DHits.put( new Integer( i ) , new HashSet<CalorimeterHit>() ); + mapLayerToSetSeedClump3DHits.put( new Integer( i ) , new HashSet<CalorimeterHit>() ); + mapLayerToSetNoSeedMip3DHits.put( new Integer( i ) , new HashSet<CalorimeterHit>() ); + mapLayerToSetNoSeedClump3DHits.put( new Integer( i ) , new HashSet<CalorimeterHit>() ); + } + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + + // list of used clusters + List<Cluster> usedClusters = new Vector<Cluster>(); + + for( Shower shower : mapShowerToSetShowers.get( showerMother ) ) + { + isUsed = mapShowerToIsUsed.get( shower ).booleanValue(); + if( isUsed ) continue; + + for( Cluster clus : shower.getShowerComponents() ) + { + //if( !mips.contains( clus ) && !clumps.contains( clus ) && !blocks.contains( clus ) ) continue; + + if( usedClusters.contains( clus ) ) continue; + else usedClusters.add( clus ); + + List<CalorimeterHit> hits = clus.getCalorimeterHits(); + + for( CalorimeterHit hit : hits ) + { + IDDecoder id = hit.getIDDecoder(); + id.setID( hit.getCellID() ); + int layer = id.getLayer(); + + int layerNumber = layer; + if( ci.getName( CalorimeterType.EM_BARREL ).equals( hit.getSubdetector().getName() ) ) layerNumber=layer; + if( ci.getName( CalorimeterType.EM_ENDCAP ).equals( hit.getSubdetector().getName() ) ) layerNumber=layer; + if( ci.getName( CalorimeterType.HAD_BARREL ).equals( hit.getSubdetector().getName() ) ) layerNumber=layer+m_numberOfLayersEMBarrel; + if( ci.getName( CalorimeterType.HAD_ENDCAP ).equals( hit.getSubdetector().getName() ) ) layerNumber=layer+m_numberOfLayersEMEndcap; + if( ci.getName( CalorimeterType.MUON_BARREL ).equals( hit.getSubdetector().getName() ) )layerNumber=layer+m_numberOfLayersEMBarrel+m_numberOfLayersHadBarrel; + + Integer ii = new Integer( layerNumber ); + + Set<CalorimeterHit> tempSetSeedMip3DHits = mapLayerToSetSeedMip3DHits.get( ii ); + if( listSeedMip3D.contains( clus ) ) tempSetSeedMip3DHits.add( hit ); + Set<CalorimeterHit> tempSetSeedClump3DHits = mapLayerToSetSeedClump3DHits.get( ii ); + if( listSeedClump3D.contains( clus ) ) tempSetSeedClump3DHits.add( hit ); + + Set<CalorimeterHit> tempSetNoSeedMip3DHits = mapLayerToSetNoSeedMip3DHits.get( ii ); + if( listNoSeedMip3D.contains( clus ) ) tempSetNoSeedMip3DHits.add( hit ); + Set<CalorimeterHit> tempSetNoSeedClump3DHits = mapLayerToSetNoSeedClump3DHits.get( ii ); + if( listNoSeedClump3D.contains( clus ) ) tempSetNoSeedClump3DHits.add( hit ); + + // + + MCParticle pHit = getMCParticleOfHit( hit ); + + List<MCParticle> listMCHit = new ArrayList<MCParticle>( mapMCtoInt.keySet() ); + + if( !listMCHit.contains( pHit ) ) + { + iMCtoInt++; + mapMCtoInt.put( pHit , new Integer( iMCtoInt ) ); + } + } + } + + Boolean tempBool = mapShowerToIsUsed.put( shower , new Boolean( true ) ); + } + + + // map from layer to seed 2D //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // map layer to Seed Mip 2D + Map<Integer,List<Cluster>> mapLayerToListSeedMip2D = new HashMap<Integer,List<Cluster>>(); + for( Integer ii : mapLayerToSetSeedMip3DHits.keySet() ) + { + List<Cluster> listSeedMip2D = new ArrayList<Cluster>(); + for( Cluster seedMip3D : listSeedMip3D ) + { + BasicCluster clusSeedMip2D = new BasicCluster(); + for( CalorimeterHit hit1 : seedMip3D.getCalorimeterHits() ) + for( CalorimeterHit hit2 : mapLayerToSetSeedMip3DHits.get( ii ) ) + if( hit1 == hit2 ) clusSeedMip2D.addHit( hit1 ); + if( clusSeedMip2D.getCalorimeterHits().size() != 0 ) listSeedMip2D.add( clusSeedMip2D ); + } + mapLayerToListSeedMip2D.put( ii , listSeedMip2D ); + } + // map layer to Seed Clump 2D + Map<Integer,List<Cluster>> mapLayerToListSeedClump2D = new HashMap<Integer,List<Cluster>>(); + for( Integer ii : mapLayerToSetSeedClump3DHits.keySet() ) + { + List<Cluster> listSeedClump2D = new ArrayList<Cluster>(); + for( Cluster seedClump3D : listSeedClump3D ) + { + BasicCluster clusSeedClump2D = new BasicCluster(); + for( CalorimeterHit hit1 : seedClump3D.getCalorimeterHits() ) + for( CalorimeterHit hit2 : mapLayerToSetSeedClump3DHits.get( ii ) ) + if( hit1 == hit2 ) clusSeedClump2D.addHit( hit1 ); + if( clusSeedClump2D.getCalorimeterHits().size() != 0 ) listSeedClump2D.add( clusSeedClump2D ); + } + mapLayerToListSeedClump2D.put( ii , listSeedClump2D ); + } + // map layer to No Seed Mip 2D + Map<Integer,List<Cluster>> mapLayerToListNoSeedMip2D = new HashMap<Integer,List<Cluster>>(); + for( Integer ii : mapLayerToSetNoSeedMip3DHits.keySet() ) + { + List<Cluster> listNoSeedMip2D = new ArrayList<Cluster>(); + for( Cluster noSeedMip3D : listNoSeedMip3D ) + { + BasicCluster clusNoSeedMip2D = new BasicCluster(); + for( CalorimeterHit hit1 : noSeedMip3D.getCalorimeterHits() ) + for( CalorimeterHit hit2 : mapLayerToSetNoSeedMip3DHits.get( ii ) ) + if( hit1 == hit2 ) clusNoSeedMip2D.addHit( hit1 ); + if( clusNoSeedMip2D.getCalorimeterHits().size() != 0 ) listNoSeedMip2D.add( clusNoSeedMip2D ); + } + mapLayerToListNoSeedMip2D.put( ii , listNoSeedMip2D ); + } + // map layer to No Seed Clump 2D + Map<Integer,List<Cluster>> mapLayerToListNoSeedClump2D = new HashMap<Integer,List<Cluster>>(); + for( int iLayer = 0 ; iLayer < totalNumberOfLayers ; iLayer++ ) + { + Integer ii = new Integer( iLayer ); + List<CalorimeterHit> listCalHits = new ArrayList<CalorimeterHit>( mapLayerToSetNoSeedClump3DHits.get( ii ) ); + List<Cluster> listClus2D = clus2DFinder.createClusters( listCalHits ); + mapLayerToListNoSeedClump2D.put( ii , listClus2D ); + } + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + + // map from seed 2D to seed 3D ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // map from seed mip 2D to seed mip 3D + Map<Cluster,Cluster> mapSeedMip2DToSeedMip3D = new HashMap<Cluster,Cluster>(); + for( Cluster seedMip3D : listSeedMip3D ) + { + CalorimeterHit negaPol = PFAUtil.getNegativePole( seedMip3D ); + for( Integer ii : mapLayerToListSeedMip2D.keySet() ) + for( Cluster seedMip2D : mapLayerToListSeedMip2D.get( ii ) ) + if( seedMip2D.getCalorimeterHits().contains( negaPol ) ) mapSeedMip2DToSeedMip3D.put( seedMip2D , seedMip3D ); + } + // map from seed clump 2D to seed clump 3D + Map<Cluster,Cluster> mapSeedClump2DToSeedClump3D = new HashMap<Cluster,Cluster>(); + for( Cluster seedClump3D : listSeedClump3D ) + { + CalorimeterHit negaPol = PFAUtil.getNegativePole( seedClump3D ); + for( Integer ii : mapLayerToListSeedClump2D.keySet() ) + for( Cluster seedClump2D : mapLayerToListSeedClump2D.get( ii ) ) + if( seedClump2D.getCalorimeterHits().contains( negaPol ) ) mapSeedMip2DToSeedMip3D.put( seedClump2D , seedClump3D ); + } + + + + // list of positive poles /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + List<Cluster> listCluster2DPositivePole = new ArrayList<Cluster>(); + for( Cluster seedMip3D : listSeedMip3D ) + { + CalorimeterHit posiPol = PFAUtil.getPositivePole( seedMip3D ); + for( Integer ii : mapLayerToListSeedMip2D.keySet() ) + for( Cluster seedMip2D : mapLayerToListSeedMip2D.get( ii ) ) + if( seedMip2D.getCalorimeterHits().contains( posiPol ) ) listCluster2DPositivePole.add( seedMip2D ); + } + for( Cluster noSeedMip3D : listNoSeedMip3D ) + { + CalorimeterHit posiPol = PFAUtil.getPositivePole( noSeedMip3D ); + for( Integer ii : mapLayerToListNoSeedMip2D.keySet() ) + for( Cluster noSeedMip2D : mapLayerToListNoSeedMip2D.get( ii ) ) + if( noSeedMip2D.getCalorimeterHits().contains( posiPol ) ) listCluster2DPositivePole.add( noSeedMip2D ); + } + for( Cluster noSeedClump3D : listNoSeedClump3D ) + { + CalorimeterHit posiPol = PFAUtil.getPositivePole( noSeedClump3D ); + for( Integer ii : mapLayerToListNoSeedClump2D.keySet() ) + for( Cluster noSeedClump2D : mapLayerToListNoSeedClump2D.get( ii ) ) + if( noSeedClump2D.getCalorimeterHits().contains( posiPol ) ) listCluster2DPositivePole.add( noSeedClump2D ); + } + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + + + // list of negative poles /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + List<Cluster> listCluster2DNegativePole = new ArrayList<Cluster>(); + for( Cluster seedMip3D : listSeedMip3D ) + { + CalorimeterHit negaPol = PFAUtil.getNegativePole( seedMip3D ); + for( Integer ii : mapLayerToListSeedMip2D.keySet() ) + for( Cluster seedMip2D : mapLayerToListSeedMip2D.get( ii ) ) + if( seedMip2D.getCalorimeterHits().contains( negaPol ) ) listCluster2DNegativePole.add( seedMip2D ); + } + for( Cluster noSeedMip3D : listNoSeedMip3D ) + { + CalorimeterHit negaPol = PFAUtil.getNegativePole( noSeedMip3D ); + for( Integer ii : mapLayerToListNoSeedMip2D.keySet() ) + for( Cluster noSeedMip2D : mapLayerToListNoSeedMip2D.get( ii ) ) + if( noSeedMip2D.getCalorimeterHits().contains( negaPol ) ) listCluster2DNegativePole.add( noSeedMip2D ); + } + for( Cluster noSeedClump3D : listNoSeedClump3D ) + { + CalorimeterHit negaPol = PFAUtil.getNegativePole( noSeedClump3D ); + for( Integer ii : mapLayerToListNoSeedClump2D.keySet() ) + for( Cluster noSeedClump2D : mapLayerToListNoSeedClump2D.get( ii ) ) + if( noSeedClump2D.getCalorimeterHits().contains( negaPol ) ) listCluster2DNegativePole.add( noSeedClump2D ); + } + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + + + // map beetween mip 2D and mip 3D , between seed clus2D and seed clus3D ///////////////////////////////////////////////////////////////////////////////////////////////////////////// + Map<Cluster,Cluster> mapSolid2DToSolid3D = new HashMap<Cluster,Cluster>(); + for( Cluster mip3D : listSeedMip3D ) { + for( Integer ii : mapLayerToListSeedMip2D.keySet() ) { + boolean isBreak = false; + for( Cluster mip2D : mapLayerToListSeedMip2D.get( ii ) ) { + for( CalorimeterHit hit1 : mip3D.getCalorimeterHits() ) { + for( CalorimeterHit hit2 : mip2D.getCalorimeterHits() ) { + if( hit1 == hit2 ) { + mapSolid2DToSolid3D.put( mip2D , mip3D ); + isBreak = true; + } if( isBreak ) break; + } if( isBreak ) break; + } if( isBreak ) break; + } + } + } + for( Cluster mip3D : listNoSeedMip3D ) { + for( Integer ii : mapLayerToListNoSeedMip2D.keySet() ) { + boolean isBreak = false; + for( Cluster mip2D : mapLayerToListNoSeedMip2D.get( ii ) ) { + for( CalorimeterHit hit1 : mip3D.getCalorimeterHits() ) { + for( CalorimeterHit hit2 : mip2D.getCalorimeterHits() ) { + if( hit1 == hit2 ) { + mapSolid2DToSolid3D.put( mip2D , mip3D ); + isBreak = true; + } if( isBreak ) break; + } if( isBreak ) break; + } if( isBreak ) break; + } + } + } + for( Cluster clump3D : listSeedClump3D ) { + for( Integer ii : mapLayerToListSeedClump2D.keySet() ) { + boolean isBreak = false; + for( Cluster clump2D : mapLayerToListSeedClump2D.get( ii ) ) { + for( CalorimeterHit hit1 : clump3D.getCalorimeterHits() ) { + for( CalorimeterHit hit2 : clump2D.getCalorimeterHits() ) { + if( hit1 == hit2 ) { + mapSolid2DToSolid3D.put( clump2D , clump3D ); + isBreak = true; + } if( isBreak ) break; + } if( isBreak ) break; + } if( isBreak ) break; + } + } + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + + + ///// shower building ///// gammapi + + List<Shower2D> listShower2D = new ArrayList<Shower2D>(); + + for( int iLayer = 0 ; iLayer < totalNumberOfLayers ; iLayer++ ) + { + Integer ii = new Integer( iLayer ); + + for( Shower2D shower2D : listShower2D ) + for( ShowerBranch2D branch2D : shower2D.getBranches() ) + branch2D.setIsBlock( false ); + + + if( mapLayerToListSeedMip2D.get( ii ).size() == 0 && mapLayerToListSeedClump2D.get( ii ).size() == 0 && + mapLayerToListNoSeedMip2D.get( ii ).size() == 0 && mapLayerToListNoSeedClump2D.get( ii ).size() == 0 ) continue; + + // 2D clusters on this layer + // seed mip + List<Cluster> listSeedMip2DOnThisLayer = new ArrayList<Cluster>(); + if( mapLayerToListSeedMip2D.get( ii ).size() != 0 ) + listSeedMip2DOnThisLayer.addAll( mapLayerToListSeedMip2D.get( ii ) ); + // seed clump + List<Cluster> listSeedClump2DOnThisLayer = new ArrayList<Cluster>(); + if( mapLayerToListSeedClump2D.get( ii ).size() != 0 ) + listSeedClump2DOnThisLayer.addAll( mapLayerToListSeedClump2D.get( ii ) ); + // no seed mip + List<Cluster> listNoSeedMip2DOnThisLayer = new ArrayList<Cluster>(); + if( mapLayerToListNoSeedMip2D.get( ii ).size() != 0 ) + listNoSeedMip2DOnThisLayer.addAll( mapLayerToListNoSeedMip2D.get( ii ) ); + // seed clump + List<Cluster> listNoSeedClump2DOnThisLayer = new ArrayList<Cluster>(); + if( mapLayerToListNoSeedClump2D.get( ii ).size() != 0 ) + listNoSeedClump2DOnThisLayer.addAll( mapLayerToListNoSeedClump2D.get( ii ) ); + + + + // joining isolated hits to other clusters ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + List<Cluster> listNoSeedClump2DOnThisLayerSingleHit = new ArrayList<Cluster>(); + List<Cluster> listNoSeedClump2DOnThisLayerMultiHit = new ArrayList<Cluster>(); + + for( Cluster clus2D : listNoSeedClump2DOnThisLayer ) + { + if( clus2D.getCalorimeterHits().size() == 1 ) listNoSeedClump2DOnThisLayerSingleHit.add( clus2D ); + else listNoSeedClump2DOnThisLayerMultiHit.add( clus2D ); + } + + for( Cluster clus2D1 : listNoSeedClump2DOnThisLayerSingleHit ) + { + Hep3Vector vPos1 = new BasicHep3Vector( clus2D1.getPosition() ); + double distMin = 1.e+99; + BasicCluster clus2Dmin = null; + for( Cluster clus2D : listNoSeedClump2DOnThisLayerMultiHit ) + for( CalorimeterHit hit : clus2D.getCalorimeterHits() ) + { + Hep3Vector vPos2 = new BasicHep3Vector( hit.getPosition() ); + Hep3Vector vDelta = VecOp.sub( vPos1 , vPos2 ); + double mDelta = vDelta.magnitude(); + if( mDelta < distMin ) + { + distMin = mDelta; + clus2Dmin = (BasicCluster)clus2D; + } + } + if( clus2Dmin != null ) + if( distMin < 3. * cellSize( ii.intValue() ) ) // 3 is a number to optimize + { + for( CalorimeterHit hit : clus2D1.getCalorimeterHits() ) clus2Dmin.addHit( hit ); + listNoSeedClump2DOnThisLayer.remove( clus2D1 ); + mapLayerToListNoSeedClump2D.get( ii ).remove( clus2D1 ); + } + } + + ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + + + // main building //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + // use the privous showers to include the clusters + + for( Shower2D shower2D : listShower2D ) + for( ShowerBranch2D branch2D : shower2D.getBranches() ) + { + if( branch2D.isPositivePole() ) continue; + Cluster baseClus2D = branch2D.getLastAddedCluster(); + + // keep the 3D mips + if( branch2D.isMip() && branch2D.isSeed() ) + { + List<Cluster> listSeedMip2DOnThisLayerTemp = new ArrayList<Cluster>(); + listSeedMip2DOnThisLayerTemp.addAll( listSeedMip2DOnThisLayer ); + + for( Cluster clus2D : listSeedMip2DOnThisLayerTemp ) + if( mapSolid2DToSolid3D.get( clus2D ) == mapSolid2DToSolid3D.get( baseClus2D ) ) + { + branch2D.addCluster( clus2D ); + branch2D.setLayerAndCluster( ii , clus2D ); + listSeedMip2DOnThisLayer.remove( clus2D ); + branch2D.setIsBlock( true ); + } + } + else if( branch2D.isMip() && !branch2D.isSeed() ) + { + List<Cluster> listNoSeedMip2DOnThisLayerTemp = new ArrayList<Cluster>(); + listNoSeedMip2DOnThisLayerTemp.addAll( listNoSeedMip2DOnThisLayer ); + + for( Cluster clus2D : listNoSeedMip2DOnThisLayerTemp ) + if( mapSolid2DToSolid3D.get( clus2D ) == mapSolid2DToSolid3D.get( baseClus2D ) ) + { + branch2D.addCluster( clus2D ); + branch2D.setLayerAndCluster( ii , clus2D ); + listNoSeedMip2DOnThisLayer.remove( clus2D ); + branch2D.setIsBlock( true ); + } + } + else if( !branch2D.isMip() && branch2D.isSeed() ) + { + List<Cluster> listSeedClump2DOnThisLayerTemp = new ArrayList<Cluster>(); + listSeedClump2DOnThisLayerTemp.addAll( listSeedClump2DOnThisLayer ); + + for( Cluster clus2D : listSeedClump2DOnThisLayerTemp ) + if( mapSolid2DToSolid3D.get( clus2D ) == mapSolid2DToSolid3D.get( baseClus2D ) ) + { + branch2D.addCluster( clus2D ); + branch2D.setLayerAndCluster( ii , clus2D ); + listSeedClump2DOnThisLayer.remove( clus2D ); + branch2D.setIsBlock( true ); + } + } + } + + //Collections.sort( listNoSeedClump2DOnThisLayer , new EnergySort() ); + + // first iteration // gaga + + Map<Cluster, List<ShowerBranch2D>> mapNoSeedClump2DToShowerBranchCandidates = new HashMap<Cluster, List<ShowerBranch2D>>(); + Map<ShowerBranch2D, List<Cluster>> mapShowerBranchToNoSeedClump2DCandidates = new HashMap<ShowerBranch2D, List<Cluster>>(); + + + + /* + // find candidates for associations + + for( Cluster clus2D : listNoSeedClump2DOnThisLayer ) + { + double proximityCut = 2. * cellSize( ii ); //// To optimize + + for( Shower2D shower2D : listShower2D ) + for( ShowerBranch2D branch2D : shower2D.getBranches() ) + { + if( branch2D.isBlock() ) continue; //toto + + Hep3Vector vdir = branch2D.getDirection(); + Cluster lastAdded = branch2D.getLastAddedCluster(); + Hep3Vector vPos = new BasicHep3Vector( lastAdded.getPosition() ); + + double proximity = 1.e+99; + for( CalorimeterHit hit : clus2D.getCalorimeterHits() ) + { + Hep3Vector hitRelPos = VecOp.sub( new BasicHep3Vector( hit.getPosition() ) , vPos ); + double dot = VecOp.dot( VecOp.unit(vdir) , hitRelPos ); + double dist = Math.sqrt( hitRelPos.magnitude()*hitRelPos.magnitude() - dot*dot ); + if( dist < proximity ) proximity = dist; + } + + if( proximity < proximityCut ) + { + List<ShowerBranch2D> showersForClus = mapNoSeedClump2DToShowerBranchCandidates.get( clus2D ); + if( showersForClus == null ) + { + showersForClus = new Vector<ShowerBranch2D>(); + mapNoSeedClump2DToShowerBranchCandidates.put( clus2D , showersForClus ); + } + showersForClus.add( branch2D ); + + List<Cluster> clustersForShower = mapShowerBranchToNoSeedClump2DCandidates.get( branch2D ); + if( clustersForShower == null ) + { + clustersForShower = new Vector<Cluster>(); + mapShowerBranchToNoSeedClump2DCandidates.put( branch2D , clustersForShower ); + } + clustersForShower.add( clus2D ); + } + } + } + + // ambiguity solving //gaga + + + for( Cluster clus2D : listNoSeedMip2DOnThisLayer ) //toto + if( listCluster2DNegativePole.contains( clus2D ) ) + listNoSeedClump2DOnThisLayer.add( clus2D ); +[truncated at 1000 lines; 1445 more skipped]
diff -u -r1.1 -r1.2 --- DebugTrackSeedMatchingDriver.java 23 Oct 2011 09:50:30 -0000 1.1 +++ DebugTrackSeedMatchingDriver.java 11 Apr 2012 15:49:35 -0000 1.2 @@ -2,7 +2,7 @@
import java.io.IOException; import java.util.*;
-import org.lcsim.recon.pfa.identifier.*;
+import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.*;
import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.structural.*; import org.lcsim.util.*; import org.lcsim.event.*;
diff -u -r1.1 -r1.2 --- DebugTrackToClusterSpecialCases.java 23 Oct 2011 09:50:30 -0000 1.1 +++ DebugTrackToClusterSpecialCases.java 11 Apr 2012 15:49:35 -0000 1.2 @@ -12,7 +12,7 @@
import org.lcsim.geometry.Calorimeter.CalorimeterType; import org.lcsim.geometry.*; import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.structural.*;
-import org.lcsim.recon.pfa.identifier.*;
+import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.*;
import java.io.IOException;
@@ -65,7 +65,7 @@
m_LQChecker = new DominantParticleBasedLQChecker( m_debugUtils );
- m_eval = new LikelihoodEvaluatorWrapper("structuralPFA/likelihood.bin");
+ m_eval = new LikelihoodEvaluatorWrapper("structuralPFA/linkLikelihood.bin");
m_inputTrackListName = inputTrackList;
diff -u -r1.1 -r1.2 --- DebugUtils.java 23 Oct 2011 09:50:30 -0000 1.1 +++ DebugUtils.java 11 Apr 2012 15:49:35 -0000 1.2 @@ -7,7 +7,7 @@
import org.lcsim.util.hitmap.*; import org.lcsim.recon.cluster.util.*; import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.structural.sharing.*;
-import org.lcsim.recon.pfa.identifier.*;
+import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.*;
import org.lcsim.mc.fast.tracking.*; import org.lcsim.event.base.*; import org.lcsim.recon.tracking.seedtracker.SeedTrack;
diff -N AmbiguousTrackToClusterMapMaker.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ AmbiguousTrackToClusterMapMaker.java 11 Apr 2012 15:49:35 -0000 1.1 @@ -0,0 +1,118 @@
+package org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier; + +import java.util.*; +import hep.physics.vec.*; +import org.lcsim.util.*; +import org.lcsim.event.*; +import org.lcsim.event.util.*; +import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.*; + +public class AmbiguousTrackToClusterMapMaker extends TrackToClusterMapMaker { + protected HelixExtrapolator m_findCluster; + public AmbiguousTrackToClusterMapMaker(HelixExtrapolator findCluster, String inputTrackList, String outputMap, String outputUnmatchedTrackList) { + super(inputTrackList, outputMap, outputUnmatchedTrackList); + m_findCluster = findCluster; + } + + protected Map<String,String> m_mapInputNameToMatchedOutputName = new HashMap<String,String>(); + protected Map<String,String> m_mapInputNameToUnmatchedOutputName = new HashMap<String,String>(); + public void addInputList(String inputName, String matchedOutputName, String unmatchedOutputName) { + m_mapInputNameToMatchedOutputName.put(inputName, matchedOutputName); + m_mapInputNameToUnmatchedOutputName.put(inputName, unmatchedOutputName); + } + + protected Map<Track,Cluster> makeMap(EventHeader event) { + // Read in inputs + List<Track> trackList = event.get(Track.class, m_inputTrackListName); + Map<String, List<Cluster>> inputLists = new HashMap<String, List<Cluster>>(); + for (String str : m_mapInputNameToMatchedOutputName.keySet()) { + List<Cluster> currentList = event.get(Cluster.class, str); + inputLists.put(str, currentList); + } + if (inputLists.size() != m_mapInputNameToMatchedOutputName.size()) { throw new AssertionError("Book-keeping error"); } + if (inputLists.size() != m_mapInputNameToUnmatchedOutputName.size()) { throw new AssertionError("Book-keeping error"); } + + // Set up matching + LocalHelixExtrapolationTrackMIPClusterMatcher mipMatch = new LocalHelixExtrapolationTrackMIPClusterMatcher(m_findCluster); + LocalHelixExtrapolationTrackClusterMatcher genMatch = new LocalHelixExtrapolationTrackClusterMatcher(m_findCluster); + DualActionTrackClusterMatcher dualMatch = new DualActionTrackClusterMatcher(mipMatch, genMatch); + mipMatch.process(event); + genMatch.process(event); + List<Cluster> allMatchableClusters = new Vector<Cluster>(); + for (List<Cluster> inputList : inputLists.values()) { + allMatchableClusters.addAll(inputList); + } + + // Do matching + Map<Track,Cluster> tracksMatchedToClusters = new HashMap<Track,Cluster>(); + Map<Cluster, List<Track>> clustersMatchedToTracks = new HashMap<Cluster, List<Track>>(); + for (Track tr : trackList) { + Cluster matchedCluster = dualMatch.matchTrackToCluster(tr, allMatchableClusters); + if (matchedCluster != null) { + // Found a match + // Optionally, handle these cases: + // * Match is to a teeny cluster piece (leftoverHitClusters) but there is structure nearby inside same DTree + // * Match is to a photon (try to split up) + // * Match is to a cluster with E>>p (try to split up) + // ... but those don't really apply here (they aren't MIPs) + tracksMatchedToClusters.put(tr, matchedCluster); + List<Track> clusTrList = clustersMatchedToTracks.get(matchedCluster); + if (clusTrList == null) { + clusTrList = new Vector<Track>(); + clustersMatchedToTracks.put(matchedCluster, clusTrList); + } + clusTrList.add(tr); + } + } + + // In this case, we don't forbid ambiguous matches where more than one track points to a single cluster. + // But we do need to identify them. For now, describe them as a MultipleTrackTrack. We may want to + // revisit this later. + Map<Track,Cluster> outputMap = new HashMap<Track,Cluster>(); + Set<Track> matchedTracks = new HashSet<Track>(); + for (Cluster clus : clustersMatchedToTracks.keySet()) { + if (clus == null) { throw new AssertionError("Null cluster!"); } + List<Track> tracksOfMatchedClus = clustersMatchedToTracks.get(clus); + if (tracksOfMatchedClus == null) { throw new AssertionError("Book-keeping error!"); } + if (tracksOfMatchedClus.size()==0) { + throw new AssertionError("Book-keeping error!"); + } else if (tracksOfMatchedClus.size()==1) { + // Unique match -- OK + Track tr = tracksOfMatchedClus.get(0); + outputMap.put(tr, clus); + } else { + // Ambiguous match -- also OK + Track mergedTrack = new MultipleTrackTrack(tracksOfMatchedClus); + outputMap.put(mergedTrack, clus); + } + matchedTracks.addAll(tracksOfMatchedClus); + } + + // Identify unmatched tracks + List<Track> unmatchedTracks = new Vector<Track>(); + unmatchedTracks.addAll(trackList); + unmatchedTracks.removeAll(matchedTracks); + + // Separate out lists of matched & unmatched clusters + for (String str : m_mapInputNameToMatchedOutputName.keySet()) { + List<Cluster> inputList = inputLists.get(str); + List<Cluster> outputListMatched = new Vector<Cluster>(); + List<Cluster> outputListUnmatched = new Vector<Cluster>(); + String matchedOutputName = m_mapInputNameToMatchedOutputName.get(str); + String unmatchedOutputName = m_mapInputNameToUnmatchedOutputName.get(str); + for (Cluster clus : inputList) { + if (outputMap.values().contains(clus)) { + outputListMatched.add(clus); + } else { + outputListUnmatched.add(clus); + } + } + event.put(matchedOutputName, outputListMatched); + event.put(unmatchedOutputName, outputListUnmatched); + } + + // All done + event.put(m_outputUnmatchedTrackListName, unmatchedTracks); + return outputMap; + } +}
diff -N CheatHelixTrackClusterMatcher.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ CheatHelixTrackClusterMatcher.java 11 Apr 2012 15:49:35 -0000 1.1 @@ -0,0 +1,46 @@
+package org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier; + +import org.lcsim.util.swim.HelixSwimmer; +import org.lcsim.event.Track; +import org.lcsim.event.MCParticle; +import hep.physics.particle.Particle; + +/** + * Attempt to match a Track to a Cluster, based on the intercept point + * on the ECAL inner surface. + * + * Works the same as SimpleTrackClusterMatcher, except that helix + * extrapolation uses truth information instead of track parameters. + * + * @version $Id: CheatHelixTrackClusterMatcher.java,v 1.1 2012/04/11 15:49:35 zaidan Exp $ + */ + +public class CheatHelixTrackClusterMatcher extends SimpleTrackClusterMatcher +{ + /** Simple constructor. */ + public CheatHelixTrackClusterMatcher() { + super(); + } + /** + * Simple constructor, setting minimum distance from track + * intecept point to cluster. + */ + public CheatHelixTrackClusterMatcher(double cut) { + super(cut); + } + + protected HelixSwimmer createSwimmer(Track tr) { + // Use same method as Steve, taking info from MC truth. + Particle particle = null; + if (tr instanceof org.lcsim.mc.fast.tracking.ReconTrack) { + particle = ((org.lcsim.mc.fast.tracking.ReconTrack)(tr)).getMCParticle(); + } + if (tr instanceof org.lcsim.event.base.BaseTrackMC) { + particle = ((org.lcsim.event.base.BaseTrackMC)(tr)).getMCParticle(); + } + // ... then feeding it into the swimmer: + HelixSwimmer swimmer = new HelixSwimmer(m_fieldStrength[2]); + swimmer.setTrack(particle.getMomentum(), particle.getOrigin(), ((int)(particle.getCharge()))); + return swimmer; + } +}
diff -N CheatHelixTrackMIPClusterMatcher.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ CheatHelixTrackMIPClusterMatcher.java 11 Apr 2012 15:49:35 -0000 1.1 @@ -0,0 +1,34 @@
+package org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier; + +import org.lcsim.util.swim.HelixSwimmer; +import org.lcsim.event.MCParticle; +import hep.physics.particle.Particle; +import org.lcsim.event.Track; + +/** + * Attempt to match a Track to a Cluster, based on the intercept point + * on the ECAL inner surface. + * + * Works the same as SimpleTrackMIPClusterMatcher, except that helix + * extrapolation uses truth information instead of track parameters. + * + * @version $Id: CheatHelixTrackMIPClusterMatcher.java,v 1.1 2012/04/11 15:49:35 zaidan Exp $ + */ + +public class CheatHelixTrackMIPClusterMatcher extends SimpleTrackMIPClusterMatcher +{ + protected HelixSwimmer createSwimmer(Track tr) { + // Use same method as Steve, taking info from MC truth. + Particle particle = null; + if (tr instanceof org.lcsim.mc.fast.tracking.ReconTrack) { + particle = ((org.lcsim.mc.fast.tracking.ReconTrack)(tr)).getMCParticle(); + } + if (tr instanceof org.lcsim.event.base.BaseTrackMC) { + particle = ((org.lcsim.event.base.BaseTrackMC)(tr)).getMCParticle(); + } + // ... then feeding it into the swimmer: + HelixSwimmer swimmer = new HelixSwimmer(m_fieldStrength[2]); + swimmer.setTrack(particle.getMomentum(), particle.getOrigin(), ((int)(particle.getCharge()))); + return swimmer; + } +}
diff -N CheatTrackClusterMatcher.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ CheatTrackClusterMatcher.java 11 Apr 2012 15:49:35 -0000 1.1 @@ -0,0 +1,396 @@
+package org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier; + +import java.util.*; +import hep.physics.vec.*; + +import org.lcsim.event.Cluster; +import org.lcsim.event.Track; +import org.lcsim.util.*; +import org.lcsim.mc.fast.tracking.ReconTrack; +import org.lcsim.recon.ztracking.cheater.CheatTrack; +import org.lcsim.event.CalorimeterHit; +import org.lcsim.event.MCParticle; +import org.lcsim.event.SimCalorimeterHit; +import hep.physics.particle.Particle; +import org.lcsim.event.EventHeader; +import org.lcsim.util.swim.HelixSwimmer; +import org.lcsim.geometry.subdetector.CylindricalCalorimeter; +import org.lcsim.geometry.Detector; +import org.lcsim.geometry.Calorimeter.CalorimeterType; +import org.lcsim.recon.util.CalorimeterInformation; +import org.lcsim.geometry.Subdetector; + +public class CheatTrackClusterMatcher extends Driver implements TrackClusterMatcher +{ + String m_mcListName; + protected CalorimeterInformation ci; + protected Subdetector emb; + protected Subdetector eme; + + public CheatTrackClusterMatcher(String mcList) { + m_mcListName = mcList; + } + + protected EventHeader m_event; + public void process(EventHeader event) { + m_event = event; + initGeometry(event); + } + + // Main interface + public Cluster matchTrackToCluster(Track tr, List<Cluster> clusters) + { + // Need truth info for this track + Particle truth = null; + if (tr instanceof ReconTrack) { + ReconTrack truthTrack = (ReconTrack) (tr); + truth = truthTrack.getMCParticle(); // returns a Particle + } else if (tr instanceof CheatTrack) { + CheatTrack truthTrack = (CheatTrack) (tr); + truth = truthTrack.getMCParticle(); // returns a MCParticle + } else { + throw new AssertionError("Don't know how to extract cheat information from this track of class "+tr.getClass().getName()); + } + if (truth == null) { + // Track has no truth information + throw new AssertionError("CheatTrackClusterMatcher called for Track with no truth information"); + } + MCParticle mctruth = (MCParticle) (truth); + + if (m_debug) { System.out.println("DEBUG: Attempting to match a track with p="+new BasicHep3Vector(tr.getMomentum()).magnitude()+" (from an MCParticle of type "+mctruth.getType()+" and p="+mctruth.getMomentum().magnitude()+") to a list of "+clusters.size()+" clusters."); } + + // Need truth info for whole event + List<MCParticle> mcList = m_event.get(MCParticle.class, m_mcListName); + + // Look up truth parents. If the tracks and MC list use the same truth + // list then this should be a 1:1 mapping. + List<MCParticle> truthParentsInList = findParentsInList(mctruth, mcList); + + // Check which clusters contributions from the MC parents: + Map<Cluster, List<CalorimeterHit>> clustersWithContributions = new HashMap<Cluster,List<CalorimeterHit>>(); + for (Cluster clus : clusters) { + List<CalorimeterHit> hits = findContributedHits(clus, truthParentsInList, mcList); + if (hits.size()>0) { + clustersWithContributions.put(clus,hits); + } + } + + // How many clusters did we match up with? + int nMatchedClusters = clustersWithContributions.keySet().size(); + if (m_debug) { System.out.println("DEBUG: Based on truth information, matched track to "+nMatchedClusters+" clusters."); } + if (nMatchedClusters == 0) { + // No match -- for example, if track didn't reach the + // calorimeters. + if (m_debug) { System.out.println("DEBUG: No matched clusters => return NULL."); } + return null; + } else if (nMatchedClusters == 1) { + // Unique/exact match + Cluster match = clustersWithContributions.keySet().iterator().next(); + if (m_debug) { System.out.println("DEBUG: Unique match => return cluster with "+match.getCalorimeterHits().size()+" hits."); } + return match; + } else { + // Non-unique match. Now we need to be cleverer... + Set<Cluster> matchedClusters = clustersWithContributions.keySet(); + if (m_debug) { System.out.println("DEBUG: Looking at "+matchedClusters.size()+" matched clusters to see which ones work best..."); } + // Look at innermost ECAL hits. + // * If there are NO clusters with a hit in either/both + // of the first two layers, return whichever cluster has + // the innermost hit (not being too fussy if >1 cluster + // has the same innermost layer since it's a bad match + // in any case). + // * If there is ONE cluster with a hit in either/both + // of the first two layers, return that cluster. + // * If there are TWO OR MORE clusters with a hit in either/both + // of the first two layers, think some more. + Cluster clusterWithInnermostHitLayer = null; + CalorimeterHit globalInnermostHitInECAL = null; + List<Cluster> clustersWithHitsInFirstTwoLayers = new Vector<Cluster>(); + for (Cluster clus : matchedClusters) { + List<CalorimeterHit> hits = clustersWithContributions.get(clus); + CalorimeterHit innermostHitInECAL = findInnermostHitInECAL(hits); + if (innermostHitInECAL != null) { + // There is an ECAL innermost hit... + int layer = getVLayer(innermostHitInECAL); + // Check if in first two layers + if (layer < 2) { + clustersWithHitsInFirstTwoLayers.add(clus); + } + // Check if is current innermost cluster + if (clusterWithInnermostHitLayer == null || layer < getVLayer(globalInnermostHitInECAL)) { + globalInnermostHitInECAL = innermostHitInECAL; + clusterWithInnermostHitLayer = clus; + } + } + if (m_debug) { + String printme = new String("DEBUG: Scanned a cluster with "+hits.size()+" hits: "); + if (innermostHitInECAL != null) { + printme += " Has ECAL hit(s). Innermost hit in layer "; + printme += getVLayer(innermostHitInECAL); + if (getVLayer(innermostHitInECAL) < 2) { + printme += " which is in first two layers"; + } + if (clusterWithInnermostHitLayer == clus) { + printme += " so this is the innermost cluster (global innermost hit layer="+getVLayer(globalInnermostHitInECAL)+")"; + } + } else { + printme += " No ECAL hits."; + } + System.out.println(printme); + } + } + if (clustersWithHitsInFirstTwoLayers.size()==0) { + // No clusters with hits in first two layers => return innermost + // (This can be null if no clusters had any ECAL hits -- that's OK.) + if (m_debug) { System.out.println("DEBUG: Didn't find any clusters with hits in first two layers => returning innermost with "+clusterWithInnermostHitLayer.getCalorimeterHits().size()+" hits"); } + return clusterWithInnermostHitLayer; + } else if (clustersWithHitsInFirstTwoLayers.size()==1) { + // Exactly one sensible match. It should be both the innermost + // cluster and the only cluster with hit(s) in first two ECAL layers. + if (clustersWithHitsInFirstTwoLayers.get(0) != clusterWithInnermostHitLayer) { throw new AssertionError("BUG"); } + if (clusterWithInnermostHitLayer == null) { throw new AssertionError("BUG"); } + if (m_debug) { System.out.println("DEBUG: Found only one cluster with a hit in either/both of first two layers => returning that one with "+clusterWithInnermostHitLayer.getCalorimeterHits().size()+" hits"); } + return clusterWithInnermostHitLayer; + } else { + // Ugly case: >1 sensible match + if (m_debug) { + System.out.println("DEBUG: For track with p="+Math.sqrt(tr.getPX()*tr.getPX()+tr.getPY()*tr.getPY()+tr.getPZ()*tr.getPZ())+", there are "+clustersWithHitsInFirstTwoLayers.size()+" matched clusters with hits in first 2 ECAL layers."); + System.out.println("DEBUG: MCParticle is a "+mctruth.getPDGID()+" with momentum "+mctruth.getMomentum().magnitude()); + System.out.println("DEBUG: Here are the truthParentsInList:"); + for (MCParticle part : truthParentsInList) { + System.out.println("DEBUG: A "+part.getPDGID()+" with momentum "+part.getMomentum().magnitude()); + } + } + // Make a HelixSwimmer to propagate the track + HelixSwimmer swimmer = new HelixSwimmer(m_fieldStrength[2]); + swimmer.setTrack(tr); + // Try swimming to the barrel: + double alphaBarrel = swimToBarrel(swimmer); + boolean validBarrel = false; + // Try swimming to the endcap: + double alphaEndcap = swimToEndcap(swimmer); + boolean validEndcap = false; + // Find intercept point + double alpha = Double.NaN; + if (isValidBarrelIntercept(swimmer, alphaBarrel)) { + alpha = alphaBarrel; + validBarrel = true; + } else if (isValidEndcapIntercept(swimmer, alphaEndcap)) { + alpha = alphaEndcap; + validEndcap = true; + } + Hep3Vector trackPoint = null; + if (Double.isNaN(alpha)) { + // Track extrapolation failed + // Not much hope here... just pick the one with the most matched hits. + if (m_debug) { System.out.println("DEBUG: Track extrapolation to ECAL failed."); } + Cluster bestMatch = null; + for (Cluster clus : clustersWithHitsInFirstTwoLayers) { + List<CalorimeterHit> hits = clustersWithContributions.get(clus); + int nMatchedHits = hits.size(); + if (bestMatch==null || nMatchedHits > clustersWithContributions.get(bestMatch).size()) { + bestMatch = clus; + } + } + if (m_debug) { System.out.println("DEBUG: Returning a cluster with "+clustersWithContributions.get(bestMatch).size()+" / "+bestMatch.getCalorimeterHits().size()+" hits matched as my best guess."); } + return bestMatch; + } else { + trackPoint = swimmer.getPointAtDistance(alpha); + if (m_debug) { System.out.println("DEBUG: Extrapolated track; Track intercept point at ("+trackPoint.x()+","+trackPoint.y()+","+trackPoint.z()+")"); } + } + // Now find the nearest one... + Cluster nearestClusterToInterceptPoint = null; + CalorimeterHit nearestHitToInterceptPoint = null; + for (Cluster clus : clustersWithHitsInFirstTwoLayers) { + List<CalorimeterHit> hits = clustersWithContributions.get(clus); + CalorimeterHit innermostHitInECAL = findInnermostHitInECAL(hits); + if (m_debug) { System.out.println("DEBUG: Cluster with "+hits.size()+" / "+clus.getCalorimeterHits().size()+" hits matched, and first ECAL hit in layer "+getVLayer(innermostHitInECAL)+" of "+innermostHitInECAL.getSubdetector().getName()); } + for (CalorimeterHit hit : hits) { + int layer = getVLayer(hit); + if (layer==0 || layer==1) { + Subdetector subdet = hit.getSubdetector(); + if (subdet == emb || subdet == eme) { + // EM -- OK + double distance = proximity(trackPoint, hit); + if (m_debug) { System.out.println("DEBUG: Hit in ECAL layer "+layer+" distance from intercept point: "+distance); } + if (nearestHitToInterceptPoint==null || distance < proximity(trackPoint, nearestHitToInterceptPoint)) { + if (m_debug) { System.out.println("DEBUG: This is the new nearest hit"); } + nearestHitToInterceptPoint = hit; + nearestClusterToInterceptPoint = clus; + } + } + } + } + } + if (nearestClusterToInterceptPoint==null) { throw new AssertionError("Inconsistency"); } + if (m_debug) { System.out.println("DEBUG: Nearest cluster has proximity of "+proximity(trackPoint, nearestHitToInterceptPoint)+" and "+nearestClusterToInterceptPoint.getCalorimeterHits().size()+" hits. Returning it."); } + return nearestClusterToInterceptPoint; + } + } + + } + + + // Utility routines + // ---------------- + + protected CalorimeterHit findInnermostHitInECAL(Cluster clus) { + return findInnermostHitInECAL(clus.getCalorimeterHits()); + } + + protected CalorimeterHit findInnermostHitInECAL(List<CalorimeterHit> hits) { + CalorimeterHit innermostHit = null; + for (CalorimeterHit hit : hits) { + int layer = getVLayer(hit); + Subdetector subdet = hit.getSubdetector(); + if ( ! subdet.isCalorimeter() ) { throw new AssertionError("Cluster hit outside calorimeter"); } + if (subdet == emb || subdet == eme) { + // EM -- OK + if (innermostHit==null || getVLayer(innermostHit)>layer) { + innermostHit = hit; + } + } + } + return innermostHit; + } + + protected int getVLayer(CalorimeterHit hit) { + if (hit==null) { throw new AssertionError("hit is null"); } + org.lcsim.geometry.IDDecoder id = hit.getIDDecoder(); + id.setID(hit.getCellID()); + int layer = id.getVLayer(); + return layer; + } + + protected List<CalorimeterHit> findContributedHits(Cluster clus, List<MCParticle> relevantParticles, List<MCParticle> allParticles) { + Vector<CalorimeterHit> output = new Vector<CalorimeterHit>(); + for (CalorimeterHit hit : clus.getCalorimeterHits()) { + boolean relevantContributionToHit = false; + Set<MCParticle> particles = findMCParticles(hit, allParticles); + for (MCParticle part : particles) { + if (relevantParticles.contains(part)) { + relevantContributionToHit = true; + break; + } + } + if (relevantContributionToHit) { + output.add(hit); + } + } + return output; + } + + protected Set<MCParticle> findMCParticles(CalorimeterHit hit, List<MCParticle> mcList) { + if ( ! (hit instanceof SimCalorimeterHit) ) { + throw new AssertionError("Non-simulated hit!"); + } else { + SimCalorimeterHit simHit = (SimCalorimeterHit) (hit); + Set<MCParticle> contributingParticlesFromList = new HashSet<MCParticle>(); + int nContributingParticles = simHit.getMCParticleCount(); + for (int i=0; i<nContributingParticles; i++) { + MCParticle part = simHit.getMCParticle(i); + List<MCParticle> parentsInList = findParentsInList(part, mcList); + contributingParticlesFromList.addAll(parentsInList); + } + return contributingParticlesFromList; + } + } + + protected List<MCParticle> findParentsInList(MCParticle part, List<MCParticle> mcList) { + List<MCParticle> outputList = new Vector<MCParticle>(); + if (mcList.contains(part)) { + // Already in there + outputList.add(part); + } else { + // Not in there -- recurse up through parents + List<MCParticle> parents = part.getParents(); + if (parents.size()==0) { + // Ran out of options -- add nothing and return below + } else { + for (MCParticle parent : parents) { + List<MCParticle> ancestorsInList = findParentsInList(parent, mcList); + outputList.addAll(ancestorsInList); + } + } + } + return outputList; + } + + protected double proximity(Hep3Vector point, CalorimeterHit hit) { + Hep3Vector hitPosition = new BasicHep3Vector(hit.getPosition()); + double distance = VecOp.sub(hitPosition, point).magnitude(); + return distance; + } + + protected double swimToBarrel(HelixSwimmer swimmer) { + // Look for a hit in the first layer of the ECAL barrel + return swimmer.getDistanceToRadius(m_ECAL_barrel_r); + } + protected double swimToEndcap(HelixSwimmer swimmer) { + // Look for a hit in the first layer of the ECAL endcap + double distanceToEndcap1 = swimmer.getDistanceToZ(m_ECAL_endcap_z); + double distanceToEndcap2 = swimmer.getDistanceToZ(-m_ECAL_endcap_z); + if (distanceToEndcap1>0) { + return distanceToEndcap1; + } else { + return distanceToEndcap2; + } + } + protected boolean isValidBarrelIntercept(HelixSwimmer swimmer, double alpha) { + // Must have -m_ECAL_barrel_z <= z <= +m_ECAL_barrel_z (within errors) + double uncertainty = 0.0; + Hep3Vector intercept = swimmer.getPointAtDistance(alpha); + double z = intercept.z(); + boolean zInRange = (z >= m_ECAL_barrel_zmin-uncertainty && z <= m_ECAL_barrel_zmax+uncertainty); + return zInRange; + } + protected boolean isValidEndcapIntercept(HelixSwimmer swimmer, double alpha) { + // Must have m_ECAL_endcap_rmin <= r <= m_ECAL_endcap_rmax (within errors) + double uncertainty = 0.0; + Hep3Vector intercept = swimmer.getPointAtDistance(alpha); + double r = Math.sqrt(intercept.x()*intercept.x() + intercept.y()*intercept.y()); + boolean rInRange = (r >= m_ECAL_endcap_rmin-uncertainty && r <= m_ECAL_endcap_rmax+uncertainty); + return rInRange; + } + + public void initGeometry(EventHeader event) + { + if(!m_init) + { + if(ci == null) + { + ci = CalorimeterInformation.instance(); + emb = ci.getSubdetector(CalorimeterType.EM_BARREL); + eme = ci.getSubdetector(CalorimeterType.EM_ENDCAP); + } + m_ECAL_barrel_zmin = ci.getZMin(CalorimeterType.EM_BARREL); + m_ECAL_barrel_zmax = ci.getZMax(CalorimeterType.EM_BARREL); + m_ECAL_barrel_r = emb.getLayering().getDistanceToLayerSensorMid(0); + m_ECAL_endcap_z = eme.getLayering().getDistanceToLayerSensorMid(0); + m_ECAL_endcap_rmin = ci.getRMin(CalorimeterType.EM_ENDCAP); + m_ECAL_endcap_rmax = ci.getRMax(CalorimeterType.EM_ENDCAP); + double[] zero = {0, 0, 0}; + m_fieldStrength = event.getDetector().getFieldMap().getField(zero); + m_init = true; + if (m_debug) { + System.out.println(this.getClass().getName()+": Init: ECAL barrel zmin="+m_ECAL_barrel_zmin); + System.out.println(this.getClass().getName()+": Init: ECAL barrel zmax="+m_ECAL_barrel_zmax); + System.out.println(this.getClass().getName()+": Init: ECAL barrel r="+m_ECAL_barrel_r); + System.out.println(this.getClass().getName()+": Init: ECAL endcap z="+m_ECAL_endcap_z); + System.out.println(this.getClass().getName()+": Init: ECAL endcap rmin="+m_ECAL_endcap_rmin); + System.out.println(this.getClass().getName()+": Init: ECAL endcap rmax="+m_ECAL_endcap_rmax); + } + } + } + + public void setDebug(boolean debug) { m_debug = debug; } + + protected boolean m_init = false; + protected double m_ECAL_barrel_zmin; + protected double m_ECAL_barrel_zmax; + protected double m_ECAL_barrel_r; + protected double m_ECAL_endcap_z; + protected double m_ECAL_endcap_rmin; + protected double m_ECAL_endcap_rmax; + protected boolean m_debug = false; + protected double[] m_fieldStrength; +}
diff -N DualActionTrackClusterMatcher.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ DualActionTrackClusterMatcher.java 11 Apr 2012 15:49:35 -0000 1.1 @@ -0,0 +1,55 @@
+package org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier; + +import java.util.*; +import org.lcsim.event.*; +import org.lcsim.recon.cluster.mipfinder.*; + +/** + * A utility class for matching tracks to clusters. + * + * This class doesn't do the clustering itself -- instead, it takes two other + * TrackClusterMatchers and delegates to them. It first tries to match the + * track to a MIP cluster using the first TrackClusterMatcher; if that fails, + * it will try to match the track to any cluster using the second + * TrackClusterMatcher. + * + * For now, MIPs are identified by checking whether the Cluster is an instance + * of org.lcsim.recon.cluster.mipfinder.MIPCluster + * + * @author Mat Charles + * @version $Id: DualActionTrackClusterMatcher.java,v 1.1 2012/04/11 15:49:35 zaidan Exp $ + */ + +public class DualActionTrackClusterMatcher implements TrackClusterMatcher { + + TrackClusterMatcher m_mipTrackClusterMatcher; + TrackClusterMatcher m_genericTrackClusterMatcher; + + /** Constructor: Supply the two TrackClusterMatchers that the matching is delegated to. */ + public DualActionTrackClusterMatcher(TrackClusterMatcher mipTrackClusterMatcher, TrackClusterMatcher genericTrackClusterMatcher) { + m_mipTrackClusterMatcher = mipTrackClusterMatcher; + m_genericTrackClusterMatcher = genericTrackClusterMatcher; + } + + /** Main interface. */ + public Cluster matchTrackToCluster(Track tr, List<Cluster> clusters) { + // First try the MIPs... + List<Cluster> mipClusters = new Vector<Cluster>(); + for (Cluster clus : clusters) { + // This is a bit of an ugly cross-check... would be better to be given a list + // of clusters, or to pull one down from the event by name. + if (clus instanceof MIPCluster) { + mipClusters.add(clus); + } + } + + Cluster matchedMIP = m_mipTrackClusterMatcher.matchTrackToCluster(tr, mipClusters); + if (matchedMIP != null) { + return matchedMIP; + } + + // That didn't work -- now try generic match + Cluster matchedClus = m_genericTrackClusterMatcher.matchTrackToCluster(tr, clusters); + return matchedClus; + } +}
diff -N FlexibleHelixExtrapolator.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ FlexibleHelixExtrapolator.java 11 Apr 2012 15:49:35 -0000 1.1 @@ -0,0 +1,81 @@
+package org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier; + +import hep.physics.vec.*; +import java.util.*; + +import org.lcsim.event.EventHeader; +import org.lcsim.event.Track; +import org.lcsim.event.base.BaseTrackMC; + +public class FlexibleHelixExtrapolator extends HelixExtrapolator +{ + private LocalHelixExtrapolator m_LocalHelixExtrapolator = null; + private TrackHelixExtrapolator m_TrackHelixExtrapolator = null; + private HelixExtrapolator m_currentLiveExtrapolator = null; + + public FlexibleHelixExtrapolator() { + super(); + m_LocalHelixExtrapolator = new LocalHelixExtrapolator(); + m_TrackHelixExtrapolator = new TrackHelixExtrapolator(); + } + + // Main interface + + // This is where the track is specified -- decide at this point which + // kind of extrapolator to use. + public HelixExtrapolationResult performExtrapolation(Track tr) { + if (tr == null) { + // Null track -- blank everything and return failure + m_currentLiveExtrapolator = null; + return null; + } else if (tr instanceof BaseTrackMC || tr instanceof org.lcsim.mc.fast.tracking.ReconTrack) { + m_currentLiveExtrapolator = m_LocalHelixExtrapolator; + } else { + m_currentLiveExtrapolator = m_TrackHelixExtrapolator; + } + return m_currentLiveExtrapolator.performExtrapolation(tr); + } + + // Main interface routines + protected Hep3Vector getInterceptPoint() { + return m_currentLiveExtrapolator.getInterceptPoint(); + } + protected Hep3Vector getTangent() { + return m_currentLiveExtrapolator.getTangent(); + } + protected Hep3Vector getTangent(Hep3Vector v) { + return m_currentLiveExtrapolator.getTangent(v); + } + protected Hep3Vector extendToEndcapLayer(int layer, Vector<Double> endcap_layering_z, double endcap_rmin, double endcap_rmax, int nsides ) { + return m_currentLiveExtrapolator.extendToEndcapLayer(layer, endcap_layering_z,endcap_rmin, endcap_rmax, nsides); + } + protected Hep3Vector extendToBarrelLayer(int layer, Vector<Double> barrel_layering_r, double barrel_zmin, double barrel_zmax, int nsides ) { + return m_currentLiveExtrapolator.extendToBarrelLayer(layer, barrel_layering_r, barrel_zmin, barrel_zmax, nsides); + } + + // Other things that need to be propagated to the extrapolator: + public void useFCAL(boolean use) { + super.useFCAL(use); + m_LocalHelixExtrapolator.useFCAL(use); + m_TrackHelixExtrapolator.useFCAL(use); + } + + public void process(EventHeader event) { + super.process(event); + m_LocalHelixExtrapolator.process(event); + m_TrackHelixExtrapolator.process(event); + } + + public void initGeometry(EventHeader event) { + super.initGeometry(event); + m_LocalHelixExtrapolator.initGeometry(event); + m_TrackHelixExtrapolator.initGeometry(event); + } + + public void setCutSeparation(double cutSeparation) { + super.setCutSeparation(cutSeparation); + m_LocalHelixExtrapolator.setCutSeparation(cutSeparation); + m_TrackHelixExtrapolator.setCutSeparation(cutSeparation); + } + +}
diff -N HelixExtrapolationResult.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ HelixExtrapolationResult.java 11 Apr 2012 15:49:35 -0000 1.1 @@ -0,0 +1,77 @@
+package org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier; + +import hep.physics.vec.*; +import java.util.*; +import org.lcsim.util.swim.HelixSwimmer; + +public class HelixExtrapolationResult +{ + HelixExtrapolator m_internalExtrapolator; + protected HelixExtrapolationResult(HelixExtrapolator extrap) { + m_internalExtrapolator = extrap; + } + + // Interface + public Hep3Vector getInterceptPoint() { + return m_internalExtrapolator.getInterceptPoint(); + } + public Hep3Vector getTangent() { + return m_internalExtrapolator.getTangent(); + } + public Hep3Vector getTangent(Hep3Vector v) { + return m_internalExtrapolator.getTangent(v); + } + public Hep3Vector extendToEndcapLayer(int layer, Vector<Double> endcap_layering_z, double endcap_rmin, double endcap_rmax, int nsides ) { + return m_internalExtrapolator.extendToEndcapLayer(layer, endcap_layering_z, endcap_rmin, endcap_rmax, nsides); + } + public Hep3Vector extendToBarrelLayer(int layer, Vector<Double> barrel_layering_r, double barrel_zmin, double barrel_zmax, int nsides ) { + return m_internalExtrapolator.extendToBarrelLayer(layer, barrel_layering_r, barrel_zmin, barrel_zmax, nsides ); + } + public Long extendToECALLayerAndFindCell(int layer) { + return m_internalExtrapolator.extendToECALLayerAndFindCell(layer); + } + public Long extendToHCALLayerAndFindCell(int layer) { + return m_internalExtrapolator.extendToHCALLayerAndFindCell(layer); + } + public Long extendToMCALLayerAndFindCell(int layer) { + return m_internalExtrapolator.extendToMCALLayerAndFindCell(layer); + } + public Hep3Vector extendToECALLayer(int layer) { + return m_internalExtrapolator.extendToECALLayer(layer); + } + public Hep3Vector extendToHCALLayer(int layer) { + return m_internalExtrapolator.extendToHCALLayer(layer); + } + public Hep3Vector extendToMCALLayer(int layer) { + return m_internalExtrapolator.extendToMCALLayer(layer); + } + public Hep3Vector extendToECALBarrelLayer(int layer) { + return m_internalExtrapolator.extendToECALBarrelLayer(layer); + } + public Hep3Vector extendToECALEndcapLayer(int layer) { + return m_internalExtrapolator.extendToECALEndcapLayer(layer); + } + public Hep3Vector extendToHCALBarrelLayer(int layer) { + return m_internalExtrapolator.extendToHCALBarrelLayer(layer); + } + public Hep3Vector extendToHCALEndcapLayer(int layer) { + return m_internalExtrapolator.extendToHCALEndcapLayer(layer); + } + public Hep3Vector extendToMCALBarrelLayer(int layer) { + return m_internalExtrapolator.extendToMCALBarrelLayer(layer); + } + public Hep3Vector extendToMCALEndcapLayer(int layer) { + return m_internalExtrapolator.extendToMCALEndcapLayer(layer); + } + public HelixSwimmer getSwimmer() + { + if(m_internalExtrapolator instanceof TrackHelixExtrapolator) + return ((TrackHelixExtrapolator) (m_internalExtrapolator)).m_swimmer; + return null; + } + public void setSwimmer(HelixSwimmer hs) + { + if(m_internalExtrapolator instanceof TrackHelixExtrapolator) + ((TrackHelixExtrapolator) (m_internalExtrapolator)).m_swimmer = hs; + } +}
diff -N HelixExtrapolator.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ HelixExtrapolator.java 11 Apr 2012 15:49:35 -0000 1.1 @@ -0,0 +1,362 @@
+package org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier; + +import java.util.*; +import hep.physics.vec.*; +import org.lcsim.geometry.Detector; +import org.lcsim.event.EventHeader; +import org.lcsim.event.Track; +import org.lcsim.util.Driver; +import org.lcsim.geometry.IDDecoder; +import org.lcsim.geometry.compact.Subdetector; +import org.lcsim.geometry.subdetector.*; +import org.lcsim.recon.util.CalorimeterInformation; +import org.lcsim.geometry.Calorimeter.CalorimeterType; + +abstract public class HelixExtrapolator extends Driver +{ + + protected boolean m_init = false; + protected double m_ECAL_barrel_zmin; + protected double m_HCAL_barrel_zmin; + protected double m_MCAL_barrel_zmin; + protected double m_ECAL_barrel_zmax; + protected double m_HCAL_barrel_zmax; + protected double m_MCAL_barrel_zmax; + protected double m_ECAL_barrel_r; + protected double m_HCAL_barrel_r; + protected double m_MCAL_barrel_r; + protected double m_ECAL_endcap_z; + protected double m_FCAL_endcap_z; + protected double m_HCAL_endcap_z; + protected double m_MCAL_endcap_z; + protected int m_ECAL_barrel_nsides; + protected int m_HCAL_barrel_nsides; + protected int m_MCAL_barrel_nsides; + protected int m_ECAL_endcap_nsides; + protected int m_FCAL_endcap_nsides; + protected int m_HCAL_endcap_nsides; + protected int m_MCAL_endcap_nsides; + protected Vector<Double> m_ECAL_barrel_layering_r; + protected Vector<Double> m_HCAL_barrel_layering_r; + protected Vector<Double> m_MCAL_barrel_layering_r; + protected Vector<Double> m_ECAL_endcap_layering_z; + protected Vector<Double> m_FCAL_endcap_layering_z; + protected Vector<Double> m_HCAL_endcap_layering_z; + protected Vector<Double> m_MCAL_endcap_layering_z; + protected double m_ECAL_endcap_rmin; + protected double m_FCAL_endcap_rmin; + protected double m_HCAL_endcap_rmin; + protected double m_MCAL_endcap_rmin; + protected double m_ECAL_endcap_rmax; + protected double m_FCAL_endcap_rmax; + protected double m_HCAL_endcap_rmax; + protected double m_MCAL_endcap_rmax; + protected double[] m_fieldStrength; + + protected double m_cutSeparation = 30.0; // 3cm + public void setCutSeparation(double cutSeparation) { m_cutSeparation = cutSeparation; } + + boolean m_barrelValid = false; + boolean m_endcapValid = false; + + EventHeader m_event = null; + Track m_track = null; + + boolean m_useFCAL = false; + boolean m_interceptsFCAL = false; + boolean m_debug = false; + CalorimeterInformation ci; + + public HelixExtrapolator() { + super(); + } + + protected HelixExtrapolator(HelixExtrapolator old) { + super(); + m_init = false; + if (old.m_init && old.m_event != null) { + initGeometry(old.m_event); + } + + setCutSeparation(old.m_cutSeparation); + m_barrelValid = old.m_barrelValid; + m_endcapValid = old.m_endcapValid; + m_event = old.m_event; + m_track = old.m_track; + useFCAL(old.m_useFCAL); + m_interceptsFCAL = old.m_interceptsFCAL; + m_debug = old.m_debug; + } + + public void setDebug(boolean debug) { + m_debug = debug; + } + + /** Allow use of FCAL. */ + public void useFCAL(boolean use) { + m_useFCAL = use; + } + + /** Process this event, storing geometry info if needed. */ + public void process(EventHeader event) { + m_event = event; + initGeometry(event); + } + + /** Initialize geometry. This is done automatically if the class is run as a driver. */ + public void initGeometry(EventHeader event) { + if(ci == null) + { + ci = CalorimeterInformation.instance(); + m_ECAL_barrel_zmin = ci.getZMin(CalorimeterType.EM_BARREL); + m_HCAL_barrel_zmin = ci.getZMin(CalorimeterType.HAD_BARREL); + m_MCAL_barrel_zmin = ci.getZMin(CalorimeterType.MUON_BARREL); + m_ECAL_barrel_zmax = ci.getZMax(CalorimeterType.EM_BARREL); + m_HCAL_barrel_zmax = ci.getZMax(CalorimeterType.HAD_BARREL); + m_MCAL_barrel_zmax = ci.getZMax(CalorimeterType.MUON_BARREL); + m_ECAL_barrel_nsides = ci.getNSides(CalorimeterType.EM_BARREL); + m_HCAL_barrel_nsides = ci.getNSides(CalorimeterType.HAD_BARREL); + m_MCAL_barrel_nsides = ci.getNSides(CalorimeterType.MUON_BARREL); + m_ECAL_endcap_nsides = ci.getNSides(CalorimeterType.EM_ENDCAP); + m_HCAL_endcap_nsides = ci.getNSides(CalorimeterType.HAD_ENDCAP); + m_MCAL_endcap_nsides = ci.getNSides(CalorimeterType.MUON_ENDCAP); + m_FCAL_endcap_nsides = ci.getNSides(CalorimeterType.LUMI); + Subdetector s = ci.getSubdetector(CalorimeterType.EM_BARREL); + double ebr0 = ci.getRMin(CalorimeterType.EM_BARREL); + if(s instanceof CylindricalBarrelCalorimeter) + { + ebr0 = 0.; + } + m_ECAL_barrel_r = ebr0 + s.getLayering().getDistanceToLayerSensorMid(0); + s = ci.getSubdetector(CalorimeterType.HAD_BARREL); + double hbr0 = ci.getRMin(CalorimeterType.HAD_BARREL); + if(s instanceof CylindricalBarrelCalorimeter) + { + hbr0 = 0.; + } + m_HCAL_barrel_r = hbr0 + s.getLayering().getDistanceToLayerSensorMid(0); + s = ci.getSubdetector(CalorimeterType.MUON_BARREL); + double mbr0 = ci.getRMin(CalorimeterType.MUON_BARREL); + if(s instanceof CylindricalBarrelCalorimeter) + { + mbr0 = 0.; + } + m_MCAL_barrel_r = mbr0 + s.getLayering().getDistanceToLayerSensorMid(0); + + s = ci.getSubdetector(CalorimeterType.EM_ENDCAP); + m_ECAL_endcap_z = s.getLayering().getDistanceToLayerSensorMid(0); + s = ci.getSubdetector(CalorimeterType.HAD_ENDCAP); + m_HCAL_endcap_z = s.getLayering().getDistanceToLayerSensorMid(0); + s = ci.getSubdetector(CalorimeterType.MUON_ENDCAP); + m_MCAL_endcap_z = s.getLayering().getDistanceToLayerSensorMid(0); + s = ci.getSubdetector(CalorimeterType.LUMI); + m_FCAL_endcap_z = s.getLayering().getDistanceToLayerSensorMid(0); + m_ECAL_endcap_rmin = ci.getRMin(CalorimeterType.EM_ENDCAP); + m_HCAL_endcap_rmin = ci.getRMin(CalorimeterType.HAD_ENDCAP); + m_MCAL_endcap_rmin = ci.getRMin(CalorimeterType.MUON_ENDCAP); + m_FCAL_endcap_rmin = ci.getRMin(CalorimeterType.LUMI); + m_ECAL_endcap_rmax = ci.getRMax(CalorimeterType.EM_ENDCAP); + m_HCAL_endcap_rmax = ci.getRMax(CalorimeterType.HAD_ENDCAP); + m_MCAL_endcap_rmax = ci.getRMax(CalorimeterType.MUON_ENDCAP); + m_FCAL_endcap_rmax = ci.getRMax(CalorimeterType.LUMI); + Detector det = event.getDetector(); + double[] zero = {0, 0, 0}; + m_fieldStrength = det.getFieldMap().getField(zero); + m_ECAL_barrel_layering_r = new Vector<Double>(); + for (int iLayer=0; iLayer<ci.getNLayers(CalorimeterType.EM_BARREL); iLayer++) { + double r = ebr0 + ci.getSubdetector(CalorimeterType.EM_BARREL).getLayering().getDistanceToLayerSensorMid(iLayer); + m_ECAL_barrel_layering_r.add(new Double(r)); + } + m_ECAL_endcap_layering_z = new Vector<Double>(); + for (int iLayer=0; iLayer<ci.getNLayers(CalorimeterType.EM_ENDCAP); iLayer++) { + double z = ci.getSubdetector(CalorimeterType.EM_ENDCAP).getLayering().getDistanceToLayerSensorMid(iLayer); + m_ECAL_endcap_layering_z.add(new Double(z)); + } + m_HCAL_barrel_layering_r = new Vector<Double>(); + for (int iLayer=0; iLayer<ci.getNLayers(CalorimeterType.HAD_BARREL); iLayer++) { + double r = hbr0 + ci.getSubdetector(CalorimeterType.HAD_BARREL).getLayering().getDistanceToLayerSensorMid(iLayer); + m_HCAL_barrel_layering_r.add(new Double(r)); + } + m_HCAL_endcap_layering_z = new Vector<Double>(); + for (int iLayer=0; iLayer<ci.getNLayers(CalorimeterType.HAD_ENDCAP); iLayer++) { + double z = ci.getSubdetector(CalorimeterType.HAD_ENDCAP).getLayering().getDistanceToLayerSensorMid(iLayer); + m_HCAL_endcap_layering_z.add(new Double(z)); + } + m_MCAL_barrel_layering_r = new Vector<Double>(); + for (int iLayer=0; iLayer<ci.getNLayers(CalorimeterType.MUON_BARREL); iLayer++) { + double r = mbr0 + ci.getSubdetector(CalorimeterType.MUON_BARREL).getLayering().getDistanceToLayerSensorMid(iLayer); + m_MCAL_barrel_layering_r.add(new Double(r)); + } + m_MCAL_endcap_layering_z = new Vector<Double>(); + for (int iLayer=0; iLayer<ci.getNLayers(CalorimeterType.MUON_ENDCAP); iLayer++) { + double z = ci.getSubdetector(CalorimeterType.MUON_ENDCAP).getLayering().getDistanceToLayerSensorMid(iLayer); + m_MCAL_endcap_layering_z.add(new Double(z)); + } + m_FCAL_endcap_layering_z = new Vector<Double>(); + for (int iLayer=0; iLayer<ci.getNLayers(CalorimeterType.LUMI); iLayer++) { + double z = ci.getSubdetector(CalorimeterType.LUMI).getLayering().getDistanceToLayerSensorMid(iLayer); + m_FCAL_endcap_layering_z.add(new Double(z)); + } + m_init = true; + } + } + + // Interface + abstract public HelixExtrapolationResult performExtrapolation(Track tr); + abstract protected Hep3Vector getInterceptPoint(); + abstract protected Hep3Vector getTangent(); + abstract protected Hep3Vector getTangent(Hep3Vector v); + abstract protected Hep3Vector extendToEndcapLayer(int layer, Vector<Double> endcap_layering_z, double endcap_rmin, double endcap_rmax, int nsides ); + abstract protected Hep3Vector extendToBarrelLayer(int layer, Vector<Double> barrel_layering_r, double barrel_zmin, double barrel_zmax, int nsides ); + + // Things that only use the interface + + protected Long extendToECALLayerAndFindCell(int layer) { + Hep3Vector point = extendToECALLayer(layer); + IDDecoder id = null; + if (m_barrelValid) { + id = ci.getIDDecoder(CalorimeterType.EM_BARREL); + if (id == null) { throw new AssertionError("Failed to find barrel ID"); } + } else if (m_endcapValid) { + id = ci.getIDDecoder(CalorimeterType.EM_ENDCAP); + if (id == null) { throw new AssertionError("Failed to find endcap ID"); } + } + if (id != null && point != null) { + if (Double.isNaN(point.x()) || Double.isNaN(point.y()) || Double.isNaN(point.z())) { throw new AssertionError("ERROR: Asked to look up call with invalid co-ordinates."); } + long cell = 0; + try + { + cell = id.findCellContainingXYZ(point); // This gets stuck for point = (NaN, NaN, NaN) + } + catch(Exception e) + { + return null; + } + id.setID(cell); + return new Long(cell); + } else { + return null; + } + } + + protected Long extendToHCALLayerAndFindCell(int layer) { + Hep3Vector point = extendToHCALLayer(layer); + IDDecoder id = null; + if (m_barrelValid) { + id = ci.getIDDecoder(CalorimeterType.HAD_BARREL); + if (id == null) { throw new AssertionError("Failed to find barrel ID"); } + } else if (m_endcapValid) { + id = ci.getIDDecoder(CalorimeterType.HAD_ENDCAP); + if (id == null) { throw new AssertionError("Failed to find endcap ID"); } + } + if (id != null && point != null) { + long cell = 0; + try + { + cell = id.findCellContainingXYZ(point); // This gets stuck for point = (NaN, NaN, NaN) + } + catch(Exception e) + { + return null; + } + id.setID(cell); + return new Long(cell); + } else { + return null; + } + } + + protected Long extendToMCALLayerAndFindCell(int layer) { + Hep3Vector point = extendToMCALLayer(layer); + IDDecoder id = null; + if (m_barrelValid) { + id = ci.getIDDecoder(CalorimeterType.MUON_BARREL); + if (id == null) { throw new AssertionError("Failed to find barrel ID"); } + } else if (m_endcapValid) { + id = ci.getIDDecoder(CalorimeterType.MUON_ENDCAP); + if (id == null) { throw new AssertionError("Failed to find endcap ID"); } + } + if (id != null && point != null) { + long cell = 0; + try + { + cell = id.findCellContainingXYZ(point); // This gets stuck for point = (NaN, NaN, NaN) + } + catch(Exception e) + { + return null; + } + id.setID(cell); + return new Long(cell); + } else { + return null; + } + } + + /** Assumes extrapolation has already been done. */ + protected Hep3Vector extendToECALLayer(int layer) { + if (m_barrelValid) { + return extendToECALBarrelLayer(layer); + } else if (m_endcapValid) { + return extendToECALEndcapLayer(layer); + } else { + // No solution + return null; + } + } + + /** Assumes extrapolation has already been done. */ + protected Hep3Vector extendToHCALLayer(int layer) { + if (m_barrelValid) { + return extendToHCALBarrelLayer(layer); + } else if (m_endcapValid) { + return extendToHCALEndcapLayer(layer); + } else { + // No solution + return null; + } + } + + /** Assumes extrapolation has already been done. */ + protected Hep3Vector extendToMCALLayer(int layer) { + if (m_barrelValid) { + return extendToMCALBarrelLayer(layer); + } else if (m_endcapValid) { + return extendToMCALEndcapLayer(layer); + } else { + // No solution + return null; + } + } + + /** Assumes extrapolation has already been done. */ + protected Hep3Vector extendToECALBarrelLayer(int layer) { + return extendToBarrelLayer(layer, m_ECAL_barrel_layering_r, m_ECAL_barrel_zmin, m_ECAL_barrel_zmax, m_ECAL_barrel_nsides); + } + /** Assumes extrapolation has already been done. */ + protected Hep3Vector extendToECALEndcapLayer(int layer) { + if (m_useFCAL && m_interceptsFCAL) { + Hep3Vector vec = extendToEndcapLayer(layer, m_FCAL_endcap_layering_z, m_FCAL_endcap_rmin, m_FCAL_endcap_rmax, m_FCAL_endcap_nsides); + if (vec != null) { + return vec; + } + } + return extendToEndcapLayer(layer, m_ECAL_endcap_layering_z, m_ECAL_endcap_rmin, m_ECAL_endcap_rmax, m_ECAL_endcap_nsides); + } + /** Assumes extrapolation has already been done. */ + protected Hep3Vector extendToHCALBarrelLayer(int layer) { + return extendToBarrelLayer(layer, m_HCAL_barrel_layering_r, m_HCAL_barrel_zmin, m_HCAL_barrel_zmax, m_HCAL_barrel_nsides); + } + /** Assumes extrapolation has already been done. */ + protected Hep3Vector extendToHCALEndcapLayer(int layer) { + return extendToEndcapLayer(layer, m_HCAL_endcap_layering_z, m_HCAL_endcap_rmin, m_HCAL_endcap_rmax, m_HCAL_endcap_nsides); + } + /** Assumes extrapolation has already been done. */ + protected Hep3Vector extendToMCALBarrelLayer(int layer) { + return extendToBarrelLayer(layer, m_MCAL_barrel_layering_r, m_MCAL_barrel_zmin, m_MCAL_barrel_zmax, m_MCAL_barrel_nsides); + } + /** Assumes extrapolation has already been done. */ + protected Hep3Vector extendToMCALEndcapLayer(int layer) { + return extendToEndcapLayer(layer, m_MCAL_endcap_layering_z, m_MCAL_endcap_rmin, m_MCAL_endcap_rmax, m_MCAL_endcap_nsides); + } +}
diff -N LocalHelixExtrapolationTrackClusterMatcher.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ LocalHelixExtrapolationTrackClusterMatcher.java 11 Apr 2012 15:49:35 -0000 1.1 @@ -0,0 +1,211 @@
+package org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier; + +import java.util.*; +import hep.physics.vec.*; +import org.lcsim.util.decision.*; + +import org.lcsim.event.Cluster; +import org.lcsim.event.CalorimeterHit; +import org.lcsim.event.EventHeader; +import org.lcsim.event.Track; +import org.lcsim.util.Driver; +import org.lcsim.recon.util.CalorimeterInformation; +import org.lcsim.geometry.Calorimeter.CalorimeterType; + +/** + * Attempt to match a Track to a Cluster. The Track is extrapolated to the inner surface + * of the ECAL with a helix derived from nearby tracker hits. We use truth information + * to find the tracker hits, so we need to look up truth information for the Track. + * + * Certain cuts are hard-coded, but additional cuts can be specified via a + * DecisionMakerPair<Track,Cluster>. + */ + + +public class LocalHelixExtrapolationTrackClusterMatcher extends Driver implements TrackClusterMatcher +{ + protected boolean init; + protected CalorimeterInformation ci; + /** Simple constructor. */ + public LocalHelixExtrapolationTrackClusterMatcher(HelixExtrapolator extrap) { + super(); + m_extrap = extrap; + init = false; + } + + /** Constructor, specifying additional cut to apply. */ + public LocalHelixExtrapolationTrackClusterMatcher(DecisionMakerPair<Track,Cluster> extraCut, HelixExtrapolator extrap) { + super(); + m_extraCut = extraCut; + m_extrap = extrap; + init = false; + } + + /** Another way to specify the additional cut. */ + public void setExtraCheck(DecisionMakerPair<Track,Cluster> extraCut) { + m_extraCut = extraCut; + } + + /** Process this event, storing geometry info if needed. */ + public void process(EventHeader event) { + if(!init) + { + ci = CalorimeterInformation.instance(); + init = true; + } + m_event = event; + m_extrap.process(event); + } + + /** + * Match this track to a cluster from the list supplied. + * Returns the best matched cluster, or null if there is no + * acceptable match. + */ + public Cluster matchTrackToCluster(Track tr, List<Cluster> clusters) { + if(!init) + { + ci = CalorimeterInformation.instance(); + init = true; + } + if (m_debug) { System.out.println("DEBUG: "+this.getClass().getName()+" trying to match track with p="+(new BasicHep3Vector(tr.getMomentum())).magnitude()+" to a list of "+clusters.size()+" clusters."); } + HelixExtrapolationResult result = m_extrap.performExtrapolation(tr); + Hep3Vector point = null; + if (result != null) { + point = result.getInterceptPoint(); + } + if (point != null) { + // Extrapolated to ECAL OK. + if (m_debug) { System.out.println("DEBUG: "+this.getClass().getName()+": extrapolated track with p="+(new BasicHep3Vector(tr.getMomentum())).magnitude()+" to r="+(Math.sqrt(point.x()*point.x()+point.y()*point.y()))+", z="+point.z()); } + // Look through clusters, starting with the nearest ones: + List<Cluster> nearestClusters = findNearestClusters(point, clusters); + for (Cluster nearbyCluster : nearestClusters) { + double separation = proximity(point, nearbyCluster); + if (m_debug) { System.out.println("DEBUG: "+this.getClass().getName()+": comparing track with p="+(new BasicHep3Vector(tr.getMomentum())).magnitude()+" to a cluster of "+nearbyCluster.getCalorimeterHits().size()+" hits at a separation of "+separation); } + if (separation > m_cutSeparation) { + // This cluster (and therefore all subsequent ones) are too far away to pass + if (m_debug) { System.out.println("DEBUG: "+this.getClass().getName()+": for track with p="+(new BasicHep3Vector(tr.getMomentum())).magnitude()+", remaining clusters are too far away (cut="+m_cutSeparation+") => no match."); } + break; + } else { + // Separation OK. Next, check that the cluster has a hit in the first n layers of the ECAL: + CalorimeterHit firstHitInECAL = findInnermostHitInECAL(nearbyCluster); + if (firstHitInECAL != null && getVLayer(firstHitInECAL) < m_cutFirstLayer) { + if (m_debug) { System.out.println("DEBUG: "+this.getClass().getName()+": comparing track with p="+(new BasicHep3Vector(tr.getMomentum())).magnitude()+" to a cluster of "+nearbyCluster.getCalorimeterHits().size()+" hits at a separation of "+separation+": First hit in ECAL is in layer "+getVLayer(firstHitInECAL)+" -- OK!"); } + // First hit layer OK. + if (m_extraCut == null || m_extraCut.valid(tr,nearbyCluster) ) { + // Extra cut not specified or passed + // All cuts passed. + if (m_debug) { System.out.println("DEBUG: "+this.getClass().getName()+": comparing track with p="+(new BasicHep3Vector(tr.getMomentum())).magnitude()+" to a cluster of "+nearbyCluster.getCalorimeterHits().size()+" hits at a separation of "+separation+": All cuts passed => accept"); } + return nearbyCluster; + } else { + if (m_debug) { System.out.println("DEBUG: "+this.getClass().getName()+": comparing track with p="+(new BasicHep3Vector(tr.getMomentum())).magnitude()+" to a cluster of "+nearbyCluster.getCalorimeterHits().size()+" hits at a separation of "+separation+": Failed extra cut ("+m_extraCut.getClass().getName()+")"); } + } + } else { + if (m_debug) { System.out.println("DEBUG: "+this.getClass().getName()+": comparing track with p="+(new BasicHep3Vector(tr.getMomentum())).magnitude()+" to a cluster of "+nearbyCluster.getCalorimeterHits().size()+" hits at a separation of "+separation+": Failed to find hit in ECAL layer < "+m_cutFirstLayer); } + } + } + } + } else { + if (m_debug) { System.out.println("DEBUG: "+this.getClass().getName()+": failed to extrapolate track => no match"); } + } + // No valid match + return null; + } + + public void setCutSeparation(double cutSeparation) { m_cutSeparation = cutSeparation; m_extrap.setCutSeparation(cutSeparation); } + public void setCutFirstLayer(int cutFirstLayer) { m_cutFirstLayer = cutFirstLayer; } + + public HelixExtrapolator getExtrapolator() { return m_extrap; } + public void setExtrapolator(HelixExtrapolator extrap) { m_extrap = extrap; } + + protected DecisionMakerPair<Track,Cluster> m_extraCut = null; + protected double m_cutSeparation = 30.0; // 3cm + protected int m_cutFirstLayer = 5; // Cluster must have a hit in in layer 0,1,2,3, or 4. + protected EventHeader m_event; + protected HelixExtrapolator m_extrap = null; + + // Utility routines + // ---------------- + + protected List<Cluster> findNearestClusters(Hep3Vector point, List<Cluster> clusterList) { + Map<Cluster,Double> mapClusterToDistance = new HashMap<Cluster, Double>(); + List<Cluster> sortedListOfClusters = new Vector<Cluster>(); + for (Cluster clus : clusterList) { + double dist = proximity(point, clus); + mapClusterToDistance.put(clus, new Double(dist)); + sortedListOfClusters.add(clus); + } + Comparator<Cluster> comp = new CompareMapping<Cluster>(mapClusterToDistance); + Collections.sort(sortedListOfClusters, comp); + return sortedListOfClusters; + } + protected CalorimeterHit findInnermostHitInECAL(Cluster clus) { + CalorimeterHit innermostHit = null; + for (CalorimeterHit hit : clus.getCalorimeterHits()) { + int layer = getVLayer(hit); + org.lcsim.geometry.Subdetector subdet = hit.getSubdetector(); + if ( ! subdet.isCalorimeter() ) { throw new AssertionError("Cluster hit outside calorimeter"); } + String name = subdet.getName(); + if (name.compareTo(ci.getName(CalorimeterType.EM_BARREL)) == 0 || name.compareTo(ci.getName(CalorimeterType.EM_ENDCAP)) == 0) { + // EM -- OK + if (innermostHit==null || getVLayer(innermostHit)>layer) { + innermostHit = hit; + } + } + } + return innermostHit; + } + protected double proximity(Hep3Vector point, Cluster clus) { + CalorimeterHit nearestHit = findNearestHit(point, clus); + return proximity(point, nearestHit); + } + protected CalorimeterHit findNearestHit(Hep3Vector point, Cluster clus) { + CalorimeterHit nearest = null; + double minDist = 0; + for (CalorimeterHit hit : clus.getCalorimeterHits()) { + Hep3Vector hitPosition = new BasicHep3Vector(hit.getPosition()); + double distance = VecOp.sub(hitPosition, point).magnitude(); + if (distance<minDist || nearest==null) { + nearest = hit; + minDist = distance; + } + } + return nearest; + } + protected double proximity(Hep3Vector point, CalorimeterHit hit) { + Hep3Vector hitPosition = new BasicHep3Vector(hit.getPosition()); + double distance = VecOp.sub(hitPosition, point).magnitude(); + return distance; + } + protected int getVLayer(CalorimeterHit hit) { + org.lcsim.geometry.IDDecoder id = hit.getIDDecoder(); + id.setID(hit.getCellID()); + int layer = id.getVLayer(); + return layer; + } + + private class CompareMapping<T> implements Comparator<T> { + public CompareMapping(Map<T,Double> map) { + m_map = map; + } + public int compare(Object o1, Object o2) { + Cluster c1 = (Cluster) o1; + Cluster c2 = (Cluster) o2; + Double D1 = m_map.get(c1); + Double D2 = m_map.get(c2); + if (D1.equals(D2)) { + // Equal + return 0; + } else if (D1.doubleValue() < D2.doubleValue()) { + return -1; + } else { + return +1; + } + } + Map<T,Double> m_map; + } + + protected boolean m_debug = false; + public void setDebug(boolean debug) { m_debug = debug ; } +} +
diff -N LocalHelixExtrapolationTrackMIPClusterMatcher.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ LocalHelixExtrapolationTrackMIPClusterMatcher.java 11 Apr 2012 15:49:35 -0000 1.1 @@ -0,0 +1,83 @@
+package org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier; + +import java.util.*; +import hep.physics.vec.*; +import org.lcsim.util.decision.*; + +import org.lcsim.event.Cluster; +import org.lcsim.event.CalorimeterHit; +import org.lcsim.geometry.Detector; +import org.lcsim.recon.cluster.util.BasicCluster; +import org.lcsim.recon.cluster.util.TensorClusterPropertyCalculator; +import org.lcsim.event.EventHeader; +import org.lcsim.util.Driver; +import org.lcsim.event.Track; +import org.lcsim.event.SimTrackerHit; +import org.lcsim.event.SimCalorimeterHit; + +public class LocalHelixExtrapolationTrackMIPClusterMatcher extends LocalHelixExtrapolationTrackClusterMatcher +{ + public LocalHelixExtrapolationTrackMIPClusterMatcher(HelixExtrapolator extrap) { + super(extrap); + } + + public LocalHelixExtrapolationTrackMIPClusterMatcher(DecisionMakerPair<Track,Cluster> extraCut, HelixExtrapolator extrap) { + super(extraCut, extrap); + } + + public Cluster matchTrackToCluster(Track tr, List<Cluster> clusters) { + HelixExtrapolationResult result = m_extrap.performExtrapolation(tr); + Hep3Vector point = null; + if (result != null) { point = result.getInterceptPoint(); } + if (point != null) { + // Extrapolated to ECAL OK. + // Now, what is the tangent at that point? + Hep3Vector tangent = m_extrap.getTangent(); + // Look through clusters, starting with the nearest ones: + List<Cluster> nearestClusters = findNearestClusters(point, clusters); + for (Cluster nearbyCluster : nearestClusters) { + double separation = proximity(point, nearbyCluster); + if (separation > m_cutSeparation) { + // This cluster (and therefore all subsequent ones) are too far away to pass + break; + } else { + // Separation OK. Next, check that the cluster has a hit in the first n layers of the ECAL: + CalorimeterHit firstHitInECAL = findInnermostHitInECAL(nearbyCluster); + if (firstHitInECAL != null && getVLayer(firstHitInECAL) < m_cutFirstLayer) { + // First hit layer OK. Next, check the dot-product of directions: + double unitDotProduct = findUnitDotProduct(tangent, nearbyCluster); + if (Math.abs(unitDotProduct) > m_cutDotProduct) { + // Dot product OK. Next, check extra cut if specified: + if (m_extraCut == null || m_extraCut.valid(tr,nearbyCluster) ) { + // Extra cut not specified or passed + // All cuts passed. + return nearbyCluster; + } + } + } + } + } + } + // No valid match + return null; + } + + protected double findUnitDotProduct(Hep3Vector tangent, Cluster clus) { + // Find the cluster direction + BasicCluster copy = new BasicCluster(); + copy.addCluster(clus); + TensorClusterPropertyCalculator calc = new TensorClusterPropertyCalculator(); + copy.setPropertyCalculator(calc); + copy.calculateProperties(); + double[][]axes = calc.getPrincipleAxis(); + Hep3Vector clusterDir = new BasicHep3Vector(axes[0][0], axes[0][1], axes[0][2]); + // Get the dot product: + double unitDotProduct = VecOp.dot(tangent, clusterDir) / (tangent.magnitude() * clusterDir.magnitude()); + if (m_debug) { + System.out.println("DEBUG: LocalHelixExtrapolationTrackMIPClusterMatcher: Computed dot product as clusterDir=("+clusterDir.x()+", "+clusterDir.y()+", "+clusterDir.z()+"), tangent=("+tangent.x()+", "+tangent.y()+", "+tangent.z()+") using "+copy.getCalorimeterHits().size()+" hits."); + } + return unitDotProduct; + } + + protected double m_cutDotProduct = 0.85; +}
diff -N LocalHelixExtrapolator.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ LocalHelixExtrapolator.java 11 Apr 2012 15:49:35 -0000 1.1 @@ -0,0 +1,462 @@
+package org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier; + +import java.util.*; +import hep.physics.vec.*; +import org.lcsim.util.decision.*; + +import hep.physics.particle.Particle; +import org.lcsim.util.swim.HelixSwimmer; +import org.lcsim.event.Cluster; +import org.lcsim.event.CalorimeterHit; +import org.lcsim.geometry.subdetector.CylindricalCalorimeter; +import org.lcsim.geometry.Detector; +import org.lcsim.recon.cluster.util.BasicCluster; +import org.lcsim.recon.cluster.util.TensorClusterPropertyCalculator; +import org.lcsim.event.EventHeader; +import org.lcsim.event.Track; +import org.lcsim.util.Driver; +import org.lcsim.event.MCParticle; +import org.lcsim.mc.fast.tracking.ReconTrack; +import org.lcsim.event.SimCalorimeterHit; +import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.TrackClusterMatcher; +import org.lcsim.event.SimTrackerHit; +import org.lcsim.mc.fast.tracking.ReconTrack; +import org.lcsim.event.base.*; +import org.lcsim.geometry.IDDecoder; + +/** + * Support class for local helix extrapolation, used to estimate + * intercept point of simulated track on an arbitrary ECAL layer. + * This will at some point be replaced by full tracking so it's + * not a good idea to depend heavily on it. + * + */ + +public class LocalHelixExtrapolator extends HelixExtrapolator +{ + double m_trackParam_xc = 0.0; + double m_trackParam_yc = 0.0; + double m_trackParam_radius = 0.0; + double m_trackParam_dz_by_dphi = 0.0; + double m_trackPoint_z = 0.0; + double m_trackPoint_phi = 0.0; + double m_track_z0 = 0.0; + double m_track_phi0 = 0.0; + double m_track_phi1 = 0.0; + boolean m_track_dphi_negative = false; + + boolean m_debugChargeFlip = false; + + // ONLY "performExtrapolation" is allowed to modify this! + private BasicHep3Vector m_lastInterceptPoint = null; + + public LocalHelixExtrapolator() { + super(); + } + + protected LocalHelixExtrapolator(LocalHelixExtrapolator old) { + super(old); + m_trackParam_xc = old.m_trackParam_xc; + m_trackParam_yc = old.m_trackParam_yc; + m_trackParam_radius = old.m_trackParam_radius; + m_trackParam_dz_by_dphi = old.m_trackParam_dz_by_dphi; + m_trackPoint_z = old.m_trackPoint_z; + m_trackPoint_phi = old.m_trackPoint_phi; + m_track_z0 = old.m_track_z0; + m_track_phi0 = old.m_track_phi0; + m_track_phi1 = old.m_track_phi1; + m_track_dphi_negative = old.m_track_dphi_negative; + m_debugChargeFlip = old.m_debugChargeFlip; + if (old.m_lastInterceptPoint == null) { + m_lastInterceptPoint = null; + } else { + m_lastInterceptPoint = new BasicHep3Vector(old.m_lastInterceptPoint.x(), old.m_lastInterceptPoint.y(), old.m_lastInterceptPoint.z()); + } + } + + public void process(EventHeader event) { + super.process(event); + } + + // Utility routines + // ---------------- + + protected Hep3Vector getInterceptPoint() { + if (m_lastInterceptPoint == null) { + return null; + } else { + return new BasicHep3Vector(m_lastInterceptPoint.x(), m_lastInterceptPoint.y(), m_lastInterceptPoint.z()); + } + } + + public HelixExtrapolationResult performExtrapolation(Track tr) { + m_track = tr; + if (tr == null) { + // Null track -- blank everything and return failure + m_trackParam_xc = m_trackParam_yc = m_trackParam_radius = m_trackParam_dz_by_dphi = m_trackPoint_z = m_trackPoint_phi = m_track_z0 = m_track_phi0 = m_track_phi1 = 0.0; + return null; + } + + // Sanity check -- check for a specific case where we try to + // extrapolate an unphysical track of class MultipleTrackTrack. + { + Class cl = tr.getClass(); + String className = cl.getName(); + boolean fake = (className.contains("MultipleTrackTrack")); + if (fake) { throw new AssertionError("Tried to do extrapolation of bogus track!"); } + } + + // Find hits. For now these are SimTrackerHits because + // of the inability to get hold of TrackerHits. + Collection<SimTrackerHit> trackerHits = findHits(tr); + + if (trackerHits.size() < 3) { + // Need at least 3 hits to make a helix. + m_lastInterceptPoint = null; + return null; + } + // Hit 0 is the closest to the calorimeter (confusing!) + SimTrackerHit hit0 = null; + SimTrackerHit hit1 = null; + SimTrackerHit hit2 = null; + for (SimTrackerHit hit : trackerHits) { + if (hit0==null || Math.abs(hit.getPoint()[2])>Math.abs(hit0.getPoint()[2])) { + hit2 = hit1; + hit1 = hit0; + hit0 = hit; + } else if (hit1==null || Math.abs(hit.getPoint()[2])>Math.abs(hit1.getPoint()[2])) { + hit2 = hit1; + hit1 = hit; + } else if (hit2==null || Math.abs(hit.getPoint()[2])>Math.abs(hit2.getPoint()[2])) { + hit2 = hit; + } + } + + // First look at the xy (circle) projection + double x0 = hit0.getPoint()[0]; + double x1 = hit1.getPoint()[0]; + double x2 = hit2.getPoint()[0]; + double y0 = hit0.getPoint()[1]; + double y1 = hit1.getPoint()[1]; + double y2 = hit2.getPoint()[1]; + double a1 = 2.0 * (x1-x0); + double a2 = 2.0 * (x2-x0); + double b1 = 2.0 * (y1-y0); + double b2 = 2.0 * (y2-y0); + double c1 = -x0*x0 -y0*y0 +x1*x1 +y1*y1; + double c2 = -x0*x0 -y0*y0 +x2*x2 +y2*y2; + // Circle center is at (x_c, y_c) + double x_c = (c1*b2-c2*b1)/(a1*b2-a2*b1); + double y_c = (c1*a2-c2*a1)/(b1*a2-b2*a1); + // Circle radius + double radiusSquared = (x_c-x0)*(x_c-x0) + (y_c-y0)*(y_c-y0); + double radius = Math.sqrt(radiusSquared); + // Now look at z/phi projection + // Watch out, this is phi around the circle, not the azimuthal angle phi + double z0 = hit0.getPoint()[2]; + double z1 = hit1.getPoint()[2]; + double z2 = hit2.getPoint()[2]; + double phi0 = Math.atan2(y0-y_c, x0-x_c); // in the range -pi through +pi + double phi1 = Math.atan2(y1-y_c, x1-x_c); + double phi2 = Math.atan2(y2-y_c, x2-x_c); + double dz = (z0-z1); + double dphi = (phi0-phi1); + while (dphi < -Math.PI) { dphi += 2.0*Math.PI; } + while (dphi > Math.PI) { dphi -= 2.0*Math.PI; } + double dz_by_dphi = dz/dphi; + m_track_dphi_negative = (dphi < 0); + // Now, try to project along to the endcaps (fairly straightforward) + double dz_to_endcap = Math.abs(m_ECAL_endcap_z) - z0; + if (z0 < 0) { + dz_to_endcap = -Math.abs(m_ECAL_endcap_z) - z0; + } + double dphi_to_endcap = dz_to_endcap / dz_by_dphi; + double found_endcap_z = z0 + dz_to_endcap; + double found_endcap_phi = phi0 + dphi_to_endcap; + double found_endcap_x = x_c + radius * Math.cos(found_endcap_phi); + double found_endcap_y = y_c + radius * Math.sin(found_endcap_phi); + double found_endcap_polar_r = Math.sqrt(found_endcap_x*found_endcap_x + found_endcap_y*found_endcap_y); + double found_endcap_polar_phi = Math.atan2(found_endcap_y, found_endcap_x); + m_endcapValid = (found_endcap_polar_r >= m_ECAL_endcap_rmin-m_cutSeparation && found_endcap_polar_r <= m_ECAL_endcap_rmax+m_cutSeparation); + boolean m_interceptsFCAL = false; + if (m_useFCAL) { + m_endcapValid = m_endcapValid || (found_endcap_polar_r >= m_FCAL_endcap_rmin-m_cutSeparation && found_endcap_polar_r <= m_FCAL_endcap_rmax+m_cutSeparation); + m_interceptsFCAL = (found_endcap_polar_r >= m_FCAL_endcap_rmin-m_cutSeparation && found_endcap_polar_r <= m_FCAL_endcap_rmax); + } + // Now project along to the barrel (harder!) + // We have phi such that (x-x_c)=a*cos(phi), (y-y_c)=a*sin(phi) + // Define theta such that x_c = b*cos(theta), y_c = b*sin(theta) + double a = radius; + double b = Math.sqrt(x_c*x_c + y_c*y_c); + double r = m_ECAL_barrel_r; // barrel radius + double cos_phi_minus_theta = (r*r - a*a - b*b) / (2.0*a*b); // Obviously, this blows up if a or b is zero + double theta = Math.atan2(y_c, x_c); // in the range (-pi, +pi) + double dphi_to_barrel = 0.0; + m_barrelValid = false; + if (cos_phi_minus_theta < -1.0) { + // No solution + } else if (cos_phi_minus_theta == -1.0) { + // Unique solution: phi = theta + pi + dphi_to_barrel = theta + Math.PI - phi0; + while (dphi_to_barrel < -Math.PI) { dphi_to_barrel += 2.0*Math.PI; } + while (dphi_to_barrel > Math.PI) { dphi_to_barrel -= 2.0*Math.PI; } + m_barrelValid = true; + } else if (cos_phi_minus_theta == 1.0) { + // Unique solution: phi = theta + dphi_to_barrel = theta - phi0; + while (dphi_to_barrel < -Math.PI) { dphi_to_barrel += 2.0*Math.PI; } + while (dphi_to_barrel > Math.PI) { dphi_to_barrel -= 2.0*Math.PI; } + m_barrelValid = true; + } else if (cos_phi_minus_theta > 1.0) { + // No solution + } else { + // Two solutions + double phi_minus_theta_first_solution = Math.acos(cos_phi_minus_theta); // in the range 0 through pi + double phi_minus_theta_second_solution = -phi_minus_theta_first_solution; // in the range -pi through 0 + double phi_first_solution = phi_minus_theta_first_solution + theta; // in the range (-pi, 2pi) + double phi_second_solution = phi_minus_theta_second_solution + theta; // in the range (-2pi, pi) + double dphi_to_barrel_firstSolution = phi_first_solution - phi0; + double dphi_to_barrel_secondSolution = phi_second_solution - phi0; + while (dphi_to_barrel_firstSolution < -Math.PI) { dphi_to_barrel_firstSolution += 2.0*Math.PI; } + while (dphi_to_barrel_secondSolution < -Math.PI) { dphi_to_barrel_secondSolution += 2.0*Math.PI; } + while (dphi_to_barrel_firstSolution > Math.PI) { dphi_to_barrel_firstSolution -= 2.0*Math.PI; } + while (dphi_to_barrel_secondSolution > Math.PI) { dphi_to_barrel_secondSolution -= 2.0*Math.PI; } + // OK, now which of the two solutions is better? + double test_dphi1 = dphi_to_barrel_firstSolution * dphi; + double test_dphi2 = dphi_to_barrel_secondSolution * dphi; + while (test_dphi1 < 0) { test_dphi1 += 2.0*Math.PI; } + while (test_dphi2 < 0) { test_dphi2 += 2.0*Math.PI; } + if (test_dphi1 < test_dphi2) { + dphi_to_barrel = dphi_to_barrel_firstSolution; + } else { + dphi_to_barrel = dphi_to_barrel_secondSolution; + } + while (dphi_to_barrel < -Math.PI) { dphi_to_barrel += 2.0*Math.PI; } + while (dphi_to_barrel > Math.PI) { dphi_to_barrel -= 2.0*Math.PI; } + m_barrelValid = true; + } + double found_barrel_z = z0 + dz_by_dphi * dphi_to_barrel; + double found_barrel_phi = phi0 + dphi_to_barrel; + double found_barrel_x = x_c + radius * Math.cos(found_barrel_phi); + double found_barrel_y = y_c + radius * Math.sin(found_barrel_phi); + double found_barrel_polar_r = Math.sqrt(found_barrel_x*found_barrel_x + found_barrel_y*found_barrel_y); + double found_barrel_polar_phi = Math.atan2(found_barrel_y, found_barrel_x); + m_barrelValid = m_barrelValid && (found_barrel_z >= m_ECAL_barrel_zmin-m_cutSeparation && found_barrel_z <= m_ECAL_barrel_zmax+m_cutSeparation); + + if (m_barrelValid && m_endcapValid) { + // Weird case: two possible solutions + // Look at which is closer to last tracker hit. + double distanceToBarrelSq = (x0-found_barrel_x)*(x0-found_barrel_x) + (y0-found_barrel_y)*(y0-found_barrel_y) + (z0-found_barrel_z)*(z0-found_barrel_z); + double distanceToEndcapSq = (x0-found_endcap_x)*(x0-found_endcap_x) + (y0-found_endcap_y)*(y0-found_endcap_y) + (z0-found_endcap_z)*(z0-found_endcap_z); + if (distanceToBarrelSq<distanceToEndcapSq) { + m_endcapValid = false; + } else { + m_barrelValid = false; + } + } + + m_trackParam_xc = x_c; + m_trackParam_yc = y_c; + m_trackParam_radius = radius; + m_trackParam_dz_by_dphi = dz_by_dphi; + m_track_phi0 = phi0; + m_track_phi1 = phi1; + m_track_z0 = z0; + if (m_endcapValid) { + m_trackPoint_z = found_endcap_z; + m_trackPoint_phi = found_endcap_phi; + m_lastInterceptPoint = new BasicHep3Vector(found_endcap_x, found_endcap_y, found_endcap_z); + HelixExtrapolationResult output = new HelixExtrapolationResult(new LocalHelixExtrapolator(this)); + if (output.getInterceptPoint() == null) { throw new AssertionError("Successful extrapolation, but intercept point is null!"); } + return output; + } + if (m_barrelValid) { + m_trackPoint_z = found_barrel_z; + m_trackPoint_phi = found_barrel_phi; + m_lastInterceptPoint = new BasicHep3Vector(found_barrel_x, found_barrel_y, found_barrel_z); + HelixExtrapolationResult output = new HelixExtrapolationResult(new LocalHelixExtrapolator(this)); + if (output.getInterceptPoint() == null) { throw new AssertionError("Successful extrapolation, but intercept point is null!"); } + return output; + } + + // No solution + m_lastInterceptPoint = null; + return null; + } + + private Collection<SimTrackerHit> findHits(Track tr) { + // Find truth particle of track: + MCParticle truth = null; + if (tr instanceof org.lcsim.mc.fast.tracking.ReconTrack) { + org.lcsim.mc.fast.tracking.ReconTrack reconTr = (org.lcsim.mc.fast.tracking.ReconTrack) (tr); + truth = (MCParticle)(reconTr.getMCParticle()); + } else if (tr instanceof BaseTrackMC) { + truth = ((BaseTrackMC)(tr)).getMCParticle(); + } + // Look up all hits in event: + List<SimTrackerHit> trackerHits = new Vector<SimTrackerHit>(); + trackerHits.addAll(m_event.get(org.lcsim.event.SimTrackerHit.class, "TkrBarrHits")); + trackerHits.addAll(m_event.get(org.lcsim.event.SimTrackerHit.class, "TkrEndcapHits")); + // Find hits that match track: + List<SimTrackerHit> hitsMatched = new Vector<org.lcsim.event.SimTrackerHit>(); + for (SimTrackerHit hit : trackerHits) { + if (hit.getMCParticle() == truth) { + hitsMatched.add(hit); + } + } + return hitsMatched; + } + + /** Assumes extrapolation has already been done. */ + protected Hep3Vector getTangent() { + double dphi = 0.01; + if (m_track.getCharge() > 0.0) { dphi = -0.01; } + double dx = m_trackParam_radius * ( Math.cos(m_trackPoint_phi+dphi) - Math.cos(m_trackPoint_phi) ); + double dy = m_trackParam_radius * ( Math.sin(m_trackPoint_phi+dphi) - Math.sin(m_trackPoint_phi) ); + double dz = m_trackParam_dz_by_dphi * dphi; + Hep3Vector tangent = VecOp.unit(new BasicHep3Vector(dx,dy,dz)); + return tangent; + } + + protected Hep3Vector getTangent(Hep3Vector v){ + + double x0 = v.x(); + double y0 = v.y(); + double z0 = v.z(); + + double phi0 = Math.atan2(y0-m_trackParam_yc, x0-m_trackParam_xc); // in the range -pi through +pi + + if(m_debug){ + Hep3Vector P = new BasicHep3Vector(m_track.getMomentum()); + System.out.println("Center of radius= " + m_trackParam_xc + " " + m_trackParam_yc); + System.out.println("This position= " + x0 + " " + y0 + " " + z0); + System.out.println("phi at this point= " + phi0); + Double pT = Math.sqrt(P.x()*P.x()+P.y()*P.y()); + double zField = m_event.getDetector().getFieldMap().getField(P).z(); + double r = 1000*pT/(0.3*zField); + System.out.println("R from track = " + m_trackParam_radius); + System.out.println("R from p/0.3B= " + r + " magnetic field= " + zField); + } + + if(m_track_dphi_negative && m_track.getCharge() < 0.0) { + if (m_debugChargeFlip || m_debug) { + System.out.println("Error: rotational direction is wrong"); + System.out.println("Charge is negative but it is determined to turn clockwise"); + } + } + + double dphi = 0.01; + if (m_track.getCharge() > 0.0) { dphi = -0.01; } + double dx = m_trackParam_radius * ( Math.cos(phi0+dphi) - Math.cos(phi0) ); + double dy = m_trackParam_radius * ( Math.sin(phi0+dphi) - Math.sin(phi0) ); + double dz = m_trackParam_dz_by_dphi * dphi; + + Hep3Vector tangent = VecOp.unit(new BasicHep3Vector(dx,dy,dz)); + return tangent; + } + + protected Hep3Vector extendToBarrelLayer(int layer, Vector<Double> barrel_layering_r, double barrel_zmin, double barrel_zmax, int nsides ) + { + if (!m_barrelValid && !m_endcapValid) { return null; } + + double dphi = (m_track_phi0 - m_track_phi1); + while (dphi < -Math.PI) { dphi += 2.0*Math.PI; } + while (dphi > Math.PI) { dphi -= 2.0*Math.PI; } + double x_c = m_trackParam_xc; + double y_c = m_trackParam_yc; + double radius = m_trackParam_radius; + double dz_by_dphi = m_trackParam_dz_by_dphi; + + double a = radius; + double b = Math.sqrt(x_c*x_c + y_c*y_c); + double r = barrel_layering_r.get(layer); + double cos_phi_minus_theta = (r*r - a*a - b*b) / (2.0*a*b); // Obviously, this blows up if a or b is zero + double theta = Math.atan2(y_c, x_c); // in the range (-pi, +pi) + double dphi_to_barrel = 0.0; + if (cos_phi_minus_theta < -1.0) { + // No solution + return null; + } else if (cos_phi_minus_theta == -1.0) { + // Unique solution: phi = theta + pi + dphi_to_barrel = theta + Math.PI - m_track_phi0; + while (dphi_to_barrel < -Math.PI) { dphi_to_barrel += 2.0*Math.PI; } + while (dphi_to_barrel > Math.PI) { dphi_to_barrel -= 2.0*Math.PI; } + } else if (cos_phi_minus_theta == 1.0) { + // Unique solution: phi = theta + dphi_to_barrel = theta - m_track_phi0; + while (dphi_to_barrel < -Math.PI) { dphi_to_barrel += 2.0*Math.PI; } + while (dphi_to_barrel > Math.PI) { dphi_to_barrel -= 2.0*Math.PI; } + } else if (cos_phi_minus_theta > 1.0) { + // No solution + return null; + } else { + // Two solutions + double phi_minus_theta_first_solution = Math.acos(cos_phi_minus_theta); // in the range 0 through pi + double phi_minus_theta_second_solution = -phi_minus_theta_first_solution; // in the range -pi through 0 + double phi_first_solution = phi_minus_theta_first_solution + theta; // in the range (-pi, 2pi) + double phi_second_solution = phi_minus_theta_second_solution + theta; // in the range (-2pi, pi) + double dphi_to_barrel_firstSolution = phi_first_solution - m_track_phi0; + double dphi_to_barrel_secondSolution = phi_second_solution - m_track_phi0; + while (dphi_to_barrel_firstSolution < -Math.PI) { dphi_to_barrel_firstSolution += 2.0*Math.PI; } + while (dphi_to_barrel_secondSolution < -Math.PI) { dphi_to_barrel_secondSolution += 2.0*Math.PI; } + while (dphi_to_barrel_firstSolution > Math.PI) { dphi_to_barrel_firstSolution -= 2.0*Math.PI; } + while (dphi_to_barrel_secondSolution > Math.PI) { dphi_to_barrel_secondSolution -= 2.0*Math.PI; } + // OK, now which of the two solutions is better? + double test_dphi1 = dphi_to_barrel_firstSolution * dphi; + double test_dphi2 = dphi_to_barrel_secondSolution * dphi; + while (test_dphi1 < 0) { test_dphi1 += 2.0*Math.PI; } + while (test_dphi2 < 0) { test_dphi2 += 2.0*Math.PI; } + if (test_dphi1 < test_dphi2) { + dphi_to_barrel = dphi_to_barrel_firstSolution; + } else { + dphi_to_barrel = dphi_to_barrel_secondSolution; + } + while (dphi_to_barrel < -Math.PI) { dphi_to_barrel += 2.0*Math.PI; } + while (dphi_to_barrel > Math.PI) { dphi_to_barrel -= 2.0*Math.PI; } + } + double found_barrel_z = m_track_z0 + dz_by_dphi * dphi_to_barrel; + double found_barrel_phi = m_track_phi0 + dphi_to_barrel; + double found_barrel_x = x_c + radius * Math.cos(found_barrel_phi); + double found_barrel_y = y_c + radius * Math.sin(found_barrel_phi); + double found_barrel_polar_r = Math.sqrt(found_barrel_x*found_barrel_x + found_barrel_y*found_barrel_y); + double found_barrel_polar_phi = Math.atan2(found_barrel_y, found_barrel_x); + boolean validSolution =(found_barrel_z >= barrel_zmin-m_cutSeparation && found_barrel_z <= barrel_zmax+m_cutSeparation); + if (validSolution) { + return new BasicHep3Vector(found_barrel_x, found_barrel_y, found_barrel_z); + } else { + return null; + } + } + + protected Hep3Vector extendToEndcapLayer(int layer, Vector<Double> endcap_layering_z, double endcap_rmin, double endcap_rmax, int nsides ) + { + if (!m_barrelValid && !m_endcapValid) { return null; } + + double dphi = (m_track_phi0 - m_track_phi1); + while (dphi < -Math.PI) { dphi += 2.0*Math.PI; } + while (dphi > Math.PI) { dphi -= 2.0*Math.PI; } + double x_c = m_trackParam_xc; + double y_c = m_trackParam_yc; + double radius = m_trackParam_radius; + double dz_by_dphi = m_trackParam_dz_by_dphi; + + double previous_z = m_trackPoint_z; + double new_z = Math.abs(endcap_layering_z.get(layer)); + if (previous_z < 0) { new_z = -new_z; } + double dz = new_z - previous_z; + double deltaPhi = dz / m_trackParam_dz_by_dphi; + double phi = m_trackPoint_phi + deltaPhi; + double found_endcap_x = x_c + radius * Math.cos(phi); + double found_endcap_y = y_c + radius * Math.sin(phi); + double found_endcap_z = new_z; + double found_endcap_polar_r = Math.sqrt(found_endcap_x*found_endcap_x + found_endcap_y*found_endcap_y); + boolean validSolution = (found_endcap_polar_r >= endcap_rmin-m_cutSeparation && found_endcap_polar_r <= endcap_rmax+m_cutSeparation); + if (validSolution) { + return new BasicHep3Vector(found_endcap_x, found_endcap_y, found_endcap_z); + } else { + return null; + } + } + + +}
diff -N MIPChargedParticleMaker.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ MIPChargedParticleMaker.java 11 Apr 2012 15:49:35 -0000 1.1 @@ -0,0 +1,346 @@
+package org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier; + +import java.util.*; +import hep.physics.vec.*; +import hep.physics.particle.Particle; +import org.lcsim.event.Track; +import org.lcsim.event.ReconstructedParticle; +import org.lcsim.event.EventHeader; +import org.lcsim.util.Driver; +import org.lcsim.event.Cluster; +import org.lcsim.mc.fast.tracking.ReconTrack; +import org.lcsim.event.base.BaseReconstructedParticle; +import org.lcsim.recon.ztracking.cheater.CheatTrack; +import org.lcsim.event.MCParticle; +import org.lcsim.geometry.Detector; +import org.lcsim.event.CalorimeterHit; +import org.lcsim.recon.cluster.util.ClusterEnergyCalculator; +import hep.physics.particle.properties.ParticleType; +import org.lcsim.event.ParticleID; +import org.lcsim.event.base.BaseParticleID; +import hep.physics.particle.properties.ParticlePropertyManager; +import org.lcsim.recon.cluster.util.BasicCluster; + +/** + * Given a list of MIP clusters and a list of tracks, + * try to connect tracks to MIP segments and + * make a list of charged ReconstructedParticles. + * + * Each track is matched to exactly zero or one MIP, + * and appears in zero or one ReconstructedParticles. + * But a MIP/particle may be associated with more than + * one track. + * + * Optionally, the user may supply further list of clusters. + * If the MIP is part of one of these clusters (via Cluster.getClusters), + * then the entire cluster is added to the ReconstructedParticle instead. + * The parent must be unique. + * + * @version $Id: MIPChargedParticleMaker.java,v 1.1 2012/04/11 15:49:35 zaidan Exp $ + */ + +public class MIPChargedParticleMaker extends Driver +{ + /** Simple constructor. */ + public MIPChargedParticleMaker() { + m_clusterLists = new HashMap<String,String>(); + } + + public void setInputTrackList(String name) { m_inputTrackListName = name; } + public void setOutputTrackList(String name){ m_outputTrackListName = name; } + public void setInputMIPList(String name){ m_inputMIPListName = name; } + public void setOutputMIPList(String name){ m_outputMIPListName = name; } + public void setOutputParticleList(String name){ m_outputParticleListName = name; } + public void setTrackMatcher(TrackClusterMatcher matcher) { m_matcher = matcher; } + + protected boolean m_checkEoverP = false; + /** + * Enable/disable a check on E/p. If enabled, a calibration must + * also be specified with <code>setCalibration()</code>. + */ + public void setCheckEoverP(boolean check) { m_checkEoverP = check; } + /** + * Specify an energy calibration. This is only used for the E/p + * check, if enabled. Note that setting a calibration doesn't + * automatically enable the E/p check. + */ + public void setCalibration(ClusterEnergyCalculator calib) { m_calib = calib; } + protected ClusterEnergyCalculator m_calib = null; + + + public void addClusterList(String inputName, String outputName) { + m_clusterLists.put(inputName, outputName); + } + + boolean m_debug = false; + public void setDebug(boolean debug) { m_debug = debug; } + + protected EventHeader m_event = null; + public void process(EventHeader event) + { + super.process(event); + m_event = event; + + // Inputs: + List<Track> inputTrackList = event.get(Track.class, m_inputTrackListName); + List<Cluster> inputMIPList = event.get(Cluster.class, m_inputMIPListName); + + // Outputs + // Initially, all tracks and MIPs are unmatched. + Map<Track,Cluster> matchedTracks = new HashMap<Track,Cluster>(); + List<Track> unmatchedTracks = new Vector<Track>(inputTrackList); + List<Cluster> unmatchedMIPs = new Vector<Cluster>(inputMIPList); + List<ReconstructedParticle> outputParticleList = new Vector<ReconstructedParticle>(); + + // Optional inputs and outputs + // Output lists are initially identical to the input lists; we will + // remove clusters as they are matched. + Map<String,List<Cluster>> inputClusterLists = new HashMap<String,List<Cluster>>(); + Map<String,List<Cluster>> outputClusterLists = new HashMap<String,List<Cluster>>(); + for (String inputName : m_clusterLists.keySet()) { + String outputName = m_clusterLists.get(inputName); + List<Cluster> inputList = event.get(Cluster.class, inputName); + List<Cluster> outputList = new Vector<Cluster>(inputList); + inputClusterLists.put(inputName, inputList); + outputClusterLists.put(outputName, outputList); + } + + // Try to match each track to a MIP segment + Map<Cluster,List<Track>> matchedMIPs = new HashMap<Cluster,List<Track>>(); + for (Track tr : inputTrackList) { + Cluster matchedMIP = m_matcher.matchTrackToCluster(tr, inputMIPList); + if (matchedMIP != null) { + // Verify that the returned MIP is a member of inputMIPList + if ( !(inputMIPList.contains(matchedMIP)) ) { + throw new AssertionError("Book-keeping error: MIP Matcher must return a member of the input list or null"); + } + if ( !(matchedMIPs.keySet().contains(matchedMIP)) ) { + // First time we've seen this MIP => make its track list + matchedMIPs.put(matchedMIP, new Vector<Track>()); + } + matchedMIPs.get(matchedMIP).add(tr); + unmatchedMIPs.remove(matchedMIP); + unmatchedTracks.remove(tr); + matchedTracks.put(tr, matchedMIP); + } + } + + // Optional: Look for each MIP's parent cluster + for (Cluster matchedMIP : matchedMIPs.keySet()) { + Cluster uniqueParent = null; + for (String inputListName : m_clusterLists.keySet()) { + String outputListName = m_clusterLists.get(inputListName); + List<Cluster> inputList = inputClusterLists.get(inputListName); + List<Cluster> outputList = outputClusterLists.get(outputListName); + + for (Cluster clus : inputList) { + List<Cluster> daughters = recursivelyFindSubClusters(clus); + if (daughters.contains(matchedMIP)) { + // Found a parent containing this MIP. + if (uniqueParent != null) { + throw new AssertionError("Book-keeping error: Non-unique parent of MIP"); + } + uniqueParent = clus; + } + } + + // If we found a unique parent in this list, do book-keeping: + // 1) Remove parent from output list of unmatched clusters + // 2) Make associated track(s) point to parent cluster + if (uniqueParent != null) { + outputList.remove(uniqueParent); + for (Track tr : matchedMIPs.get(matchedMIP)) { + matchedTracks.put(tr, uniqueParent); // over-write previous mapping + } + } + } + } + + // Now that we have the track:cluster association, make output + // particles. We have to watch for the special case where >1 track + // is matched to a cluster. + Map<Cluster,BaseReconstructedParticle> matchedClusters = new HashMap<Cluster,BaseReconstructedParticle> (); + for (Track tr : matchedTracks.keySet()) { + Cluster clus = matchedTracks.get(tr); + if ( ! matchedClusters.keySet().contains(clus)) { + // This cluster hasn't been used yet -- initialize its particle + BaseReconstructedParticle part = new BaseReconstructedParticle(); + part.addCluster(clus); + matchedClusters.put(clus, part); + } + BaseReconstructedParticle part = matchedClusters.get(clus); + part.addTrack(tr); + recomputeKinematics(part); + } + + if (m_checkEoverP) { + for (BaseReconstructedParticle part : matchedClusters.values()) { + boolean energyOK = checkEoverP(part); + if (energyOK) { + outputParticleList.add(part); + } else { + // No match => undo association + // Remove track matching... + List<Track> partTracks = part.getTracks(); + unmatchedTracks.addAll(partTracks); + // Remove MIP matching... + List<Cluster> partClusters = part.getClusters(); + for (Cluster partCluster : partClusters) { + List<Cluster> daughters = recursivelyFindSubClusters(partCluster); + for (Cluster dauClus : daughters) { + if (inputMIPList.contains(dauClus)) { + unmatchedMIPs.add(dauClus); + } + } + } + // Remove macro cluster matching... + for (String inputListName : m_clusterLists.keySet()) { + String outputListName = m_clusterLists.get(inputListName); + List<Cluster> inputList = inputClusterLists.get(inputListName); + List<Cluster> outputList = outputClusterLists.get(outputListName); + for (Cluster partCluster : partClusters) { + if (inputList.contains(partCluster) && !(outputList.contains(partCluster))) { + outputList.add(partCluster); + } + } + } + } + } + } else { + outputParticleList.addAll(matchedClusters.values()); + } + + // Write out + event.put(m_outputTrackListName, unmatchedTracks); + event.put(m_outputMIPListName, unmatchedMIPs); + event.put(m_outputParticleListName, outputParticleList); + for (String inputName : m_clusterLists.keySet()) { + String outputName = m_clusterLists.get(inputName); + List<Cluster> outputList = outputClusterLists.get(outputName); + event.put(outputName, outputList); + } + + if (m_debug) { + System.out.println("MIPChargedParticleMaker: Read in "+inputTrackList.size()+" tracks and "+inputMIPList.size()+" MIP clusters; wrote out " + +outputParticleList.size()+" matched particles, "+unmatchedTracks.size()+" unmatched tracks, "+unmatchedMIPs.size()+" unmatched MIP clusters"); + } + } + + /** + * Internal utility routine + */ + protected List<Cluster> recursivelyFindSubClusters(Cluster clus) + { + List<Cluster> output = new Vector<Cluster>(); + for (Cluster dau : clus.getClusters()) { + output.addAll(recursivelyFindSubClusters(dau)); + } + output.add(clus); + return output; + } + + protected TrackClusterMatcher m_matcher; + protected String m_inputTrackListName; + protected String m_outputTrackListName; + protected String m_inputMIPListName; + protected String m_outputMIPListName; + protected String m_outputParticleListName; + protected Map<String,String> m_clusterLists; + + protected boolean checkEoverP(BaseReconstructedParticle part) { + // We don't expect an exact match due to resolution, energy lost + // to fragments etc., but a good portion of the energy should be + // in the cluster + + // Check energy and uncertainty from calorimeter: + BasicCluster macroCluster = new BasicCluster(); + for (Cluster clus : part.getClusters()) { + macroCluster.addCluster(clus); + } + double estimatedClusterEnergy = estimateClusterEnergy(macroCluster); + double estimatedClusterEnergyUncertainty = 0.7 * Math.sqrt(estimatedClusterEnergy); // 70%/sqrt(E) for hadrons + + // Check energy from tracks + double estimatedTrackEnergy = 0.0; + for (Track tr : part.getTracks()) { + double[] trackMomentum = tr.getMomentum(); + double trackMomentumMagSq = trackMomentum[0]*trackMomentum[0] + trackMomentum[1]*trackMomentum[1] + trackMomentum[2]*trackMomentum[2]; + double trackMomentumMag = Math.sqrt(trackMomentumMagSq); + double massPion = 0.14; + double energyReleaseIfPion = Math.sqrt(trackMomentumMagSq + massPion*massPion); + estimatedTrackEnergy += energyReleaseIfPion; + } + + double allowedVariation = 3.0; // 3sigma + boolean energyDiffOK_pion = Math.abs((estimatedTrackEnergy - estimatedClusterEnergy)/estimatedClusterEnergyUncertainty) < allowedVariation; + boolean energyDiffOK = energyDiffOK_pion; + + if (m_debug) { + System.out.println("DEBUG [MIP]: Checked E/P; found cluster E="+estimatedClusterEnergy + +" +- "+estimatedClusterEnergyUncertainty + +" and track E="+estimatedTrackEnergy + +" => "+energyDiffOK); + } + + return energyDiffOK; + } + + private double estimateClusterEnergy(Cluster clus) { + return m_calib.getEnergy(clus); + } + + // This particle has >= 1 track. + // Recompute its 4-vector and mass. + protected void recomputeKinematics(BaseReconstructedParticle part) { + if (part.getTracks().size() < 1 ) { throw new AssertionError("Charged particle with no tracks: internal consistency failure."); } + double energy = 0.0; + int charge = 0; + double px = 0.0; + double py = 0.0; + double pz = 0.0; + Particle firstTruthParticle = null; + for (Track tr : part.getTracks()) { + double[] trackMomentum = tr.getMomentum(); + double trackMomentumMagSq = (trackMomentum[0]*trackMomentum[0] + trackMomentum[1]*trackMomentum[1] + trackMomentum[2]*trackMomentum[2]); + double mass = 0.140; + Particle truthParticle = null; + if (tr instanceof ReconTrack) { + truthParticle = ((ReconTrack)(tr)).getMCParticle(); + } else if (tr instanceof CheatTrack) { + truthParticle = ((CheatTrack)(tr)).getMCParticle(); + } + if (truthParticle != null) { + mass = truthParticle.getMass(); + if (firstTruthParticle == null) { firstTruthParticle = truthParticle; } + } + double trackEnergy = Math.sqrt(trackMomentumMagSq + mass*mass); + energy += trackEnergy; + charge += tr.getCharge(); + px += trackMomentum[0]; + py += trackMomentum[1]; + pz += trackMomentum[2]; + } + Hep3Vector threeMomentum = new BasicHep3Vector(px,py,pz); + HepLorentzVector fourMomentum = new BasicHepLorentzVector(energy, threeMomentum); + part.setCharge(charge); + part.set4Vector(fourMomentum); + part.setMass(fourMomentum.magnitude()); + if (part.getTracks().size() == 1) { + // Unique track => PID etc somewhat well-defined + ParticleType type = null; + if (firstTruthParticle != null) { + type = firstTruthParticle.getType(); + } else { + int pdg = 211 * charge; // everything is a pion + type = ParticlePropertyManager.getParticlePropertyProvider().get(pdg); + } + BaseParticleID pid = new BaseParticleID(type); + part.addParticleID(pid); + part.setParticleIdUsed(pid); + part.setReferencePoint(new BasicHep3Vector(part.getTracks().get(0).getReferencePoint())); + } else { + // Multiple tracks => some quantities not well-defined + // Leave at defaults. + } + } +}
diff -N MultipleTrackTrack.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ MultipleTrackTrack.java 11 Apr 2012 15:49:35 -0000 1.1 @@ -0,0 +1,53 @@
+package org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier; + +import java.util.*; +import org.lcsim.util.*; +import org.lcsim.event.*; +import org.lcsim.event.base.*; + +/** + * Utility class for the case when multiple tracks point to the same + * cluster in the calorimeter and can't be disentangled. + * + * @version $Id: MultipleTrackTrack.java,v 1.1 2012/04/11 15:49:35 zaidan Exp $ + * @author [log in to unmask] + */ + +public class MultipleTrackTrack extends BaseTrack { + protected Collection<Track> m_tracks; + + /** FIXME: Needs to be protected! Public for now while adjusting contrib... */ + public MultipleTrackTrack(Collection<Track> tracks) { + m_tracks = tracks; + } + public List<Track> getTracks() { return new Vector<Track>(m_tracks); } + public int getCharge() { + int chargeSum = 0; + for (Track tr : m_tracks) { + chargeSum += tr.getCharge(); + } + return chargeSum; + } + public double[] getMomentum() { + double[] mom = new double[3]; + mom[0] = this.getPX(); + mom[1] = this.getPY(); + mom[2] = this.getPZ(); + return mom; + } + public double getPX() { + double psum = 0.0; + for (Track tr : m_tracks) { psum += tr.getPX(); } + return psum; + } + public double getPY() { + double psum = 0.0; + for (Track tr : m_tracks) { psum += tr.getPY(); } + return psum; + } + public double getPZ() { + double psum = 0.0; + for (Track tr : m_tracks) { psum += tr.getPZ(); } + return psum; + } +}
diff -N SequentialTrackClusterMatcher.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ SequentialTrackClusterMatcher.java 11 Apr 2012 15:49:35 -0000 1.1 @@ -0,0 +1,44 @@
+package org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier; + +import java.util.*; +import org.lcsim.event.*; +import org.lcsim.recon.cluster.mipfinder.*; + +/** + * A utility class for matching tracks to clusters. + * + * This class doesn't do the clustering itself -- instead, it takes other + * TrackClusterMatchers and delegates to them, trying to match the + * track to a cluster using them in sequence. + * + * @author Mat Charles + * @version $Id: SequentialTrackClusterMatcher.java,v 1.1 2012/04/11 15:49:35 zaidan Exp $ + */ + +public class SequentialTrackClusterMatcher implements TrackClusterMatcher { + + List<TrackClusterMatcher> m_matchers = null; + + /** Simple constructor. */ + public SequentialTrackClusterMatcher() { + m_matchers = new Vector<TrackClusterMatcher>(); + } + + /** Main interface. */ + public Cluster matchTrackToCluster(Track tr, List<Cluster> clusters) { + for (TrackClusterMatcher matcher : m_matchers) { + Cluster matchedCluster = matcher.matchTrackToCluster(tr, clusters); + if (matchedCluster != null) { + // Found a match + return matchedCluster; + } + } + // Nothing found + return null; + } + + /** Add a TrackClusterMatcher to the end of the list to use. */ + public void addMatcher(TrackClusterMatcher matcher) { + m_matchers.add(matcher); + } +}
diff -N SimpleChargedParticleMaker.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ SimpleChargedParticleMaker.java 11 Apr 2012 15:49:35 -0000 1.1 @@ -0,0 +1,165 @@
+package org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier; + +import java.util.*; +import hep.physics.vec.*; +import hep.physics.particle.Particle; + +import org.lcsim.event.Track; +import org.lcsim.event.ReconstructedParticle; +import org.lcsim.event.EventHeader; +import org.lcsim.util.Driver; +import org.lcsim.util.swim.HelixSwimmer; +import org.lcsim.event.Cluster; +import org.lcsim.event.CalorimeterHit; +import org.lcsim.geometry.subdetector.CylindricalCalorimeter; +import org.lcsim.geometry.Detector; +import org.lcsim.recon.cluster.util.BasicCluster; +import org.lcsim.recon.cluster.util.TensorClusterPropertyCalculator; +import org.lcsim.mc.fast.tracking.ReconTrack; +import org.lcsim.event.base.BaseReconstructedParticle; +import org.lcsim.recon.ztracking.cheater.CheatTrack; +import hep.physics.particle.properties.ParticleType; +import org.lcsim.event.ParticleID; +import org.lcsim.event.base.BaseParticleID; +import hep.physics.particle.properties.ParticlePropertyManager; + +/** + * Given lists of clusters and tracks, make a list of charged + * ReconstructedParticles. + * + * Currently, PID is done by cheating. + * + * @version $Id: SimpleChargedParticleMaker.java,v 1.1 2012/04/11 15:49:35 zaidan Exp $ + */ + +public class SimpleChargedParticleMaker extends Driver +{ + /** Simple constructor. */ + public SimpleChargedParticleMaker() { + } + + public void setInputTrackList(String name) { m_inputTrackListName = name; } + public void setOutputTrackList(String name){ m_outputTrackListName = name; } + public void setInputClusterList(String name){ m_inputClusterListName = name; } + public void setOutputParticleList(String name){ m_outputParticleListName = name; } + public void setTrackMatcher(TrackClusterMatcher matcher) { m_matcher = matcher; } + + public void process(EventHeader event) + { + super.process(event); + + // Inputs: + List<Track> inputTrackList = event.get(Track.class, m_inputTrackListName); + List<Cluster> inputClusterList = event.get(Cluster.class, m_inputClusterListName); + + // Outputs: + Map<Track,Cluster> matchedTracks = new HashMap<Track,Cluster>(); + List<Track> unmatchedTracks = new Vector<Track>(inputTrackList); + List<ReconstructedParticle> outputParticleList = new Vector<ReconstructedParticle>(); + + // Try to match each track to a cluster + for (Track tr : inputTrackList) { + Cluster matchedCluster = m_matcher.matchTrackToCluster(tr, inputClusterList); + if (matchedCluster != null) { + matchedTracks.put(tr, matchedCluster); + unmatchedTracks.remove(tr); + // Should we check that the matched cluster is in the + // expected list? + } + } + + // Now, we need to make output particles for the tracks. + // We have to watch out for the special cases where: + // >1 track is matched to a cluster + Map<Cluster,BaseReconstructedParticle> matchedClusters = new HashMap<Cluster,BaseReconstructedParticle> (); + for (Track tr : matchedTracks.keySet()) { + Cluster clus = matchedTracks.get(tr); + if ( ! matchedClusters.keySet().contains(clus)) { + // This cluster hasn't been used yet -- initialize its particle + BaseReconstructedParticle part = new BaseReconstructedParticle(); + part.addCluster(clus); + matchedClusters.put(clus, part); + } + // Now update the particle for the track: + BaseReconstructedParticle part = matchedClusters.get(clus); + part.addTrack(tr); + recomputeKinematics(part); + } + outputParticleList.addAll(matchedClusters.values()); + + // Write out + event.put(m_outputTrackListName, unmatchedTracks); + event.put(m_outputParticleListName, outputParticleList); + + if (m_debug) { + System.out.println("SimpleChargedParticleMaker: Read in "+inputTrackList.size()+" tracks and "+inputClusterList.size()+" clusters; wrote out " + +outputParticleList.size()+" matched particles and "+unmatchedTracks.size()+" unmatched tracks"); + } + } + + boolean m_debug = false; + public void setDebug(boolean debug) { m_debug = debug; } + + protected TrackClusterMatcher m_matcher; + String m_inputTrackListName; + String m_outputTrackListName; + String m_inputClusterListName; + String m_outputParticleListName; + + // This particle has >= 1 track. + // Recompute its 4-vector and mass. + protected void recomputeKinematics(BaseReconstructedParticle part) { + if (part.getTracks().size() < 1 ) { throw new AssertionError("Charged particle with no tracks: internal consistency failure."); } + double energy = 0.0; + int charge = 0; + double px = 0.0; + double py = 0.0; + double pz = 0.0; + Particle firstTruthParticle = null; + for (Track tr : part.getTracks()) { + double[] trackMomentum = tr.getMomentum(); + double trackMomentumMagSq = (trackMomentum[0]*trackMomentum[0] + trackMomentum[1]*trackMomentum[1] + trackMomentum[2]*trackMomentum[2]); + double mass = 0.140; + Particle truthParticle = null; + if (tr instanceof ReconTrack) { + truthParticle = ((ReconTrack)(tr)).getMCParticle(); + } else if (tr instanceof CheatTrack) { + truthParticle = ((CheatTrack)(tr)).getMCParticle(); + } + if (truthParticle != null) { + mass = truthParticle.getMass(); + if (firstTruthParticle == null) { firstTruthParticle = truthParticle; } + } + double trackEnergy = Math.sqrt(trackMomentumMagSq + mass*mass); + energy += trackEnergy; + charge += tr.getCharge(); + px += trackMomentum[0]; + py += trackMomentum[1]; + pz += trackMomentum[2]; + } + Hep3Vector threeMomentum = new BasicHep3Vector(px,py,pz); + HepLorentzVector fourMomentum = new BasicHepLorentzVector(energy, threeMomentum); + part.setCharge(charge); + part.set4Vector(fourMomentum); + part.setMass(fourMomentum.magnitude()); + if (part.getTracks().size() == 1) { + // Unique track => PID etc somewhat well-defined + ParticleType type = null; + if (firstTruthParticle != null) { + type = firstTruthParticle.getType(); + } else { + int pdg = 211 * charge; // everything is a pion + type = ParticlePropertyManager.getParticlePropertyProvider().get(pdg); + } + BaseParticleID pid = new BaseParticleID(type); + part.addParticleID(pid); + part.setParticleIdUsed(pid); + part.setReferencePoint(new BasicHep3Vector(part.getTracks().get(0).getReferencePoint())); + } else { + // Multiple tracks => some quantities not well-defined + // Leave at defaults. + } + } +} + +
diff -N SimpleNeutralParticleMaker.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ SimpleNeutralParticleMaker.java 11 Apr 2012 15:49:35 -0000 1.1 @@ -0,0 +1,121 @@
+package org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier; + +import java.util.*; +import hep.physics.vec.Hep3Vector; +import hep.physics.vec.BasicHep3Vector; +import hep.physics.vec.VecOp; +import hep.physics.vec.BasicHepLorentzVector; +import hep.physics.vec.HepLorentzVector; +import hep.physics.particle.properties.ParticlePropertyProvider; +import hep.physics.particle.properties.ParticlePropertyManager; +import hep.physics.particle.properties.ParticleType; +import org.lcsim.event.ReconstructedParticle; +import org.lcsim.event.base.BaseReconstructedParticle; +import org.lcsim.event.EventHeader; +import org.lcsim.event.ParticleID; +import org.lcsim.event.base.BaseParticleID; +import org.lcsim.util.Driver; +import org.lcsim.event.Cluster; +import org.lcsim.event.base.BaseReconstructedParticle; +import org.lcsim.event.CalorimeterHit; +import org.lcsim.geometry.Detector; +import org.lcsim.event.MCParticle; +import org.lcsim.recon.cluster.util.ClusterEnergyCalculator; + +/** + * Given lists of clusters, make a list of neutral ReconstructedParticles. + * + * Currently, PID is predetermined. + * + * @version $Id: SimpleNeutralParticleMaker.java,v 1.1 2012/04/11 15:49:35 zaidan Exp $ + */ + +public class SimpleNeutralParticleMaker extends Driver +{ + protected EventHeader m_event; + + /** + * Constructor. + * + * @param pdg The neutral particles are assumed to be of this type when calculating the 4-momentum. + */ + public SimpleNeutralParticleMaker(int pdg) { + setParticleID(pdg); + } + + // Configure + public void setInputClusterList(String name){ m_inputClusterListName = name; } + public void setOutputParticleList(String name){ m_outputParticleListName = name; } + public void setParticleID(int pdg) { + ParticlePropertyProvider mgr = ParticlePropertyManager.getParticlePropertyProvider(); + ParticleType type = mgr.get(pdg); + m_mass = type.getMass(); + m_id = new BaseParticleID(type); + } + + // Process one event + public void process(EventHeader event) + { + m_event = event; + + // Input, output: + List<Cluster> inputClusterList = event.get(Cluster.class, m_inputClusterListName); + List<ReconstructedParticle> outputParticleList = new Vector<ReconstructedParticle>(); + + for (Cluster clus : inputClusterList) { + // Create the particle + BaseReconstructedParticle part = new BaseReconstructedParticle(); + part.addCluster(clus); + // The cluster energy now includes, at a crude level, the particle mass. + double clusterEnergy = estimateClusterEnergy(clus); + Hep3Vector threeMomentum = computeMomentum(clusterEnergy, clus); + // Set the other particle properties that are needed to render + // properly in the event display. + HepLorentzVector fourMomentum = new BasicHepLorentzVector(clusterEnergy, threeMomentum); + part.set4Vector(fourMomentum); + part.setReferencePoint(0,0,0); + part.setCharge(0); + // Set the PID and mass + part.addParticleID(m_id); + part.setParticleIdUsed(m_id); + part.setMass(m_mass); + // Add to the output list + outputParticleList.add(part); + } + + event.put(m_outputParticleListName, outputParticleList); + } + + Hep3Vector computeMomentum(double energy, Cluster clus) { + // Where is the cluster? + Hep3Vector pos = new BasicHep3Vector(clus.getPosition()); + Hep3Vector unitDirection = VecOp.unit(pos); + // Now, what's the momentum? + // p^2 = E^2 - m^2 + double momentumSquared = energy*energy - m_mass*m_mass; + if (momentumSquared < 0) { + // A low-energy cluster that we think came from a + // massive particle -- it must be very soft. + // Treat as zero momentum. + momentumSquared = 0; + } + double momentumMagnitude = Math.sqrt(momentumSquared); + Hep3Vector momentum = VecOp.mult(momentumMagnitude, unitDirection); + return momentum; + } + + protected String m_inputClusterListName; + protected String m_outputParticleListName; + protected double m_mass; + protected ParticleID m_id = null; + + protected ClusterEnergyCalculator m_calib = null; + protected double estimateClusterEnergy(Cluster clus) { + return m_calib.getEnergy(clus); + } + /** Specify what energy calibration to use. */ + public void setCalibration(ClusterEnergyCalculator calib) { m_calib = calib; } + + boolean m_debug = false; + public void setDebug(boolean debug) { m_debug = debug; } +}
diff -N SimpleTrackClusterMatcher.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ SimpleTrackClusterMatcher.java 11 Apr 2012 15:49:35 -0000 1.1 @@ -0,0 +1,478 @@
+package org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier; + +import java.util.*; +import hep.physics.vec.*; + +import org.lcsim.util.decision.*; +import org.lcsim.util.swim.HelixSwimmer; +import org.lcsim.event.Cluster; +import org.lcsim.event.CalorimeterHit; +import org.lcsim.geometry.subdetector.CylindricalCalorimeter; +import org.lcsim.geometry.Detector; +import org.lcsim.recon.cluster.util.BasicCluster; +import org.lcsim.recon.cluster.util.TensorClusterPropertyCalculator; +import org.lcsim.event.EventHeader; +import org.lcsim.event.Track; +import org.lcsim.util.Driver; +import org.lcsim.event.MCParticle; +import hep.physics.particle.Particle; +import org.lcsim.mc.fast.tracking.ReconTrack; +import org.lcsim.event.SimCalorimeterHit; +import org.lcsim.recon.cluster.util.ClusterEnergyCalculator; +import org.lcsim.geometry.Calorimeter.CalorimeterType; +import org.lcsim.recon.util.CalorimeterInformation; +import org.lcsim.geometry.Subdetector; + +/** + * Attempt to match a Track to a Cluster, based on the intercept point + * on the ECAL inner surface. + * + * Currently, the match criteria are hard-code. It would be better to + * supply them as DecisionMaker objects. + * + * @version $Id: SimpleTrackClusterMatcher.java,v 1.1 2012/04/11 15:49:35 zaidan Exp $ + */ + +public class SimpleTrackClusterMatcher extends Driver implements TrackClusterMatcher +{ + protected CalorimeterInformation ci; + protected Subdetector emb; + protected Subdetector eme; + public SimpleTrackClusterMatcher(double cut) { + m_separationCut = cut; + } + public SimpleTrackClusterMatcher() { + // Use default cuts on track-cluster matching: + // * Subdet must be EMBarrel or EMEndcap + // * First layer of cluster in ECAL must be <5 + // * Track intercept point must be within 30 mm of a cluster hit + // For now, E/p cut is handled specially + } + + protected HelixSwimmer createSwimmer(Track tr) { + HelixSwimmer swimmer = new HelixSwimmer(m_fieldStrength[2]); + swimmer.setTrack(tr); + return swimmer; + } + + /** + * Match this track to a cluster from the list supplied. + */ + public Cluster matchTrackToCluster(Track tr, List<Cluster> clusters) + { + if (m_debug) { + System.out.println("DEBUG: SimpleTrackClusterMatcher.matchTrackToCluster invoked for a list of "+clusters.size()+" clusters."); + double[] trackMom = tr.getMomentum(); + double trackMomMag = Math.sqrt(trackMom[0]*trackMom[0] + trackMom[1]*trackMom[1] + trackMom[2]*trackMom[2]); + System.out.println("DEBUG: Track has momentum "+trackMomMag+" --> ("+trackMom[0]+", "+trackMom[1]+", "+trackMom[2]+")"); + System.out.println("DEBUG: Track has reference point ("+tr.getReferencePointX()+", "+tr.getReferencePointY()+", "+tr.getReferencePointZ()+")"); + System.out.println("DEBUG: Track parameters are:" + +" d0="+tr.getTrackParameter(0) + +", phi0="+tr.getTrackParameter(1) + +", omega="+tr.getTrackParameter(2) + +", z0="+tr.getTrackParameter(3) + +", s="+tr.getTrackParameter(4) + ); + } + + // Make a HelixSwimmer to propagate the track + HelixSwimmer swimmer = createSwimmer(tr); + + // Try swimming to the barrel: + double alphaBarrel = swimToBarrel(swimmer); + boolean validBarrel = false; + // Try swimming to the endcap: + double alphaEndcap = swimToEndcap(swimmer); + boolean validEndcap = false; + + // Fixme: Here we should check that the track really does go all the + // way to the ECAL instead of stopping/decaying/interacting earlier. + double alpha = Double.NaN; + if (isValidBarrelIntercept(swimmer, alphaBarrel)) { + alpha = alphaBarrel; + validBarrel = true; + } else if (isValidEndcapIntercept(swimmer, alphaEndcap)) { + alpha = alphaEndcap; + validEndcap = true; + } + + // Did we make a successful extrapolation? + if (Double.isNaN(alpha)) { + // No -- failed + if (m_debug) { + System.out.println("DEBUG: "+this.getClass().getName()+": Failed to extrapolate: alphaBarrel="+alphaBarrel+" ("+validBarrel+"), alphaEndcap="+alphaEndcap+" ("+validEndcap+") => alpha="+alpha); + double[] trackMom = tr.getMomentum(); + double trackMomMag = Math.sqrt(trackMom[0]*trackMom[0] + trackMom[1]*trackMom[1] + trackMom[2]*trackMom[2]); + if (tr instanceof org.lcsim.mc.fast.tracking.ReconTrack) { + Particle debugTruthMatch = ((ReconTrack)(tr)).getMCParticle(); + if (debugTruthMatch != null) { + System.out.println("DEBUG: "+this.getClass().getName()+": No track match for track with p="+trackMomMag+" from truth "+debugTruthMatch.getType().getName()+" with E="+debugTruthMatch.getEnergy()+" because extrapolation failed."); + } else { + System.out.println("DEBUG: "+this.getClass().getName()+": No track match for track with p="+trackMomMag+" [no truth match] because extrapolation failed."); + } + } + } + return null; + } + if ( !(validEndcap || validBarrel) ) { + // Invalid state + throw new AssertionError("Invalid state: alpha is not NaN, but not a valid barrel or endcap intercept"); + } + if ( validEndcap && validBarrel ) { + throw new AssertionError("Invalid state: barrel="+validBarrel+", endcap="+validEndcap); + } + + // If we reach here, we extrapolated to the barrel or + // to the endcap successfully. + + Cluster matchedCluster = findMatchedCluster(tr, swimmer, alpha, clusters); + if (matchedCluster != null) { + // Matched OK + if (m_debug) { + Hep3Vector momentumVec = new BasicHep3Vector(tr.getMomentum()); + System.out.println("DEBUG: "+this.getClass().getName()+": Extrapolated track to cluster (momentum = "+momentumVec.magnitude()+")"); + double[] trackMom = tr.getMomentum(); + double trackMomMag = Math.sqrt(trackMom[0]*trackMom[0] + trackMom[1]*trackMom[1] + trackMom[2]*trackMom[2]); + if (tr instanceof org.lcsim.mc.fast.tracking.ReconTrack) { + Particle debugTruthMatch = ((ReconTrack)(tr)).getMCParticle(); + if (debugTruthMatch != null) { + System.out.println("DEBUG: "+this.getClass().getName()+": Track match for track with p="+trackMomMag+" from truth "+debugTruthMatch.getType().getName()+" with E="+debugTruthMatch.getEnergy()); + } else { + System.out.println("DEBUG: "+this.getClass().getName()+": Track match for track with p="+trackMomMag+" [no truth match]"); + } + } + } + return matchedCluster; + } else { + // No match found + if (m_debug) { + Hep3Vector momentumVec = new BasicHep3Vector(tr.getMomentum()); + System.out.println("DEBUG: "+this.getClass().getName()+": Failed to extrapolate track (momentum = "+momentumVec.magnitude()+")"); + double[] trackMom = tr.getMomentum(); + double trackMomMag = Math.sqrt(trackMom[0]*trackMom[0] + trackMom[1]*trackMom[1] + trackMom[2]*trackMom[2]); + if (tr instanceof org.lcsim.mc.fast.tracking.ReconTrack) { + Particle debugTruthMatch = ((ReconTrack)(tr)).getMCParticle(); + if (debugTruthMatch != null) { + System.out.println("DEBUG: "+this.getClass().getName()+": No track match for track with p="+trackMomMag+" from truth "+debugTruthMatch.getType().getName()+" with E="+debugTruthMatch.getEnergy()); + } else { + System.out.println("DEBUG: "+this.getClass().getName()+": No track match for track with p="+trackMomMag+" [no truth match]"); + } + } + } + + return null; + } + } + + protected boolean m_checkEoverP = false; + public void setCheckEoverP(boolean checkEoverP) { + m_checkEoverP = checkEoverP; + if (m_debug) { System.out.println("DEBUG: set m_checkEoverP to "+m_checkEoverP); } + } + + protected double swimToBarrel(HelixSwimmer swimmer) { + // Look for a hit in the first layer of the ECAL barrel + return swimmer.getDistanceToRadius(m_ECAL_barrel_r); + } + protected double swimToEndcap(HelixSwimmer swimmer) { + // Look for a hit in the first layer of the ECAL endcap + double distanceToEndcap1 = swimmer.getDistanceToZ(m_ECAL_endcap_z); + double distanceToEndcap2 = swimmer.getDistanceToZ(-m_ECAL_endcap_z); + if (distanceToEndcap1>0) { + return distanceToEndcap1; + } else { + return distanceToEndcap2; + } + } + protected boolean isValidBarrelIntercept(HelixSwimmer swimmer, double alpha) { + // Must have -m_ECAL_barrel_z <= z <= +m_ECAL_barrel_z (within errors) + double uncertainty = m_separationCut; + Hep3Vector intercept = swimmer.getPointAtDistance(alpha); + double z = intercept.z(); + boolean zInRange = (z >= m_ECAL_barrel_zmin-uncertainty && z <= m_ECAL_barrel_zmax+uncertainty); + return zInRange; + } + protected boolean isValidEndcapIntercept(HelixSwimmer swimmer, double alpha) { + // Must have m_ECAL_endcap_rmin <= r <= m_ECAL_endcap_rmax (within errors) + double uncertainty = m_separationCut; + Hep3Vector intercept = swimmer.getPointAtDistance(alpha); + double r = Math.sqrt(intercept.x()*intercept.x() + intercept.y()*intercept.y()); + boolean rInRange = (r >= m_ECAL_endcap_rmin-uncertainty && r <= m_ECAL_endcap_rmax+uncertainty); + return rInRange; + } + + protected Cluster findMatchedCluster(Track tr, HelixSwimmer swimmer, double alpha, List<Cluster> clusters) + { + if (m_debug) { System.out.println("DEBUG: SimpleTrackClusterMatched.findMatchedCluster() invoked for a list of "+clusters.size()+" clusters."); } + // Find the track intercept and direction + swimmer.setTrack(tr); + Hep3Vector trackPoint = swimmer.getPointAtDistance(alpha); + + List<Cluster> nearestClusters = findNearestClusters(trackPoint, clusters); + for (Cluster nearbyCluster : nearestClusters) { + // Obtain geometrical info: + CalorimeterHit nearestHit = findNearestHit(trackPoint, nearbyCluster); + double separation = proximity(trackPoint, nearestHit); + CalorimeterHit firstHitInECAL = findInnermostHitInECAL(nearbyCluster); + org.lcsim.geometry.Subdetector subdet = nearestHit.getSubdetector(); + // Make cuts: + boolean goodSubDet = (subdet == emb) || (subdet == eme); + boolean goodFirstLayer = (firstHitInECAL!=null && getVLayer(firstHitInECAL) < 5); + double separationCut = m_separationCut; + boolean goodSeparation = (separation < separationCut); + boolean foundMatch = goodSubDet && goodFirstLayer && goodSeparation; + if (m_debug) { + String printme = new String(); + printme += "Debug: Match track to cluster = ["+foundMatch+"] since"; + printme += " subdet="+subdet.getName()+" ["+goodSubDet+"] and"; + if (firstHitInECAL!=null) { + printme += " firstlayer="+getVLayer(firstHitInECAL)+" ["+goodFirstLayer+"] and"; + } else { + printme += " firstlayer=null ["+goodFirstLayer+"] and"; + } + printme += " separation="+separation+" ["+goodSeparation+"]"; + System.out.println(printme); + String debugContributions = new String(); + debugContributions += "DEBUG: Cluster contents:"; + Map<MCParticle, List<CalorimeterHit>> tmpMap = new HashMap<MCParticle, List<CalorimeterHit>>(); + for (CalorimeterHit hit : nearbyCluster.getCalorimeterHits()) { + SimCalorimeterHit simhit = (SimCalorimeterHit) (hit); + for (int i=0; i<simhit.getMCParticleCount(); i++) { + MCParticle hitPart = simhit.getMCParticle(i); + if ( ! (tmpMap.keySet().contains(hitPart)) ) { + tmpMap.put(hitPart, new Vector<CalorimeterHit>()); + } + tmpMap.get(hitPart).add(hit); + } + } + for (MCParticle hitPart : tmpMap.keySet()) { + debugContributions += " "; + debugContributions += hitPart.getType().getName(); + debugContributions += " (E="; + debugContributions += hitPart.getEnergy(); + debugContributions += ", hits="; + debugContributions += tmpMap.get(hitPart).size(); + debugContributions += ")"; + } + System.out.println(debugContributions); + } + if (foundMatch) { + // Geometrically, it looks good. + // Is it sensible in terms of energy? + + boolean energyOK = true; // By default, always pass + if (m_checkEoverP) { + boolean passesEoverPcut = checkEoverP(nearbyCluster, tr); + energyOK = energyOK && passesEoverPcut; + } + + if (energyOK) { + // Matches OK + return nearbyCluster; + } else { + // This cluster isn't a good match -- ignore it. + } + } + } + // No match + return null; + } + + protected boolean checkEoverP(Cluster nearbyCluster, Track tr) { + // We don't expect an exact match due to resolution, energy lost + // to fragments etc., but a good portion of the energy should be + // in the cluster + + // Check energy and uncertainty from calorimeter: + double estimatedClusterEnergy = estimateClusterEnergy(nearbyCluster); + double estimatedClusterEnergyUncertainty = 0.7 * Math.sqrt(estimatedClusterEnergy); // 70%/sqrt(E) for hadrons + + // Check energy from track + double[] trackMomentum = tr.getMomentum(); + double trackMomentumMagSq = trackMomentum[0]*trackMomentum[0] + trackMomentum[1]*trackMomentum[1] + trackMomentum[2]*trackMomentum[2]; + double trackMomentumMag = Math.sqrt(trackMomentumMagSq); + double massPion = 0.14; + double massProton = 0.94; + double energyReleaseIfPion = Math.sqrt(trackMomentumMagSq + massPion*massPion); + double energyReleaseIfProton = trackMomentumMag; + double energyReleaseIfAntiproton = trackMomentumMag + massProton + massProton; + + double allowedVariation = 3.0; // 3sigma + boolean energyDiffOK_pion = Math.abs((energyReleaseIfPion - estimatedClusterEnergy)/estimatedClusterEnergyUncertainty) < allowedVariation; + boolean energyDiffOK_proton = Math.abs((energyReleaseIfProton - estimatedClusterEnergy)/estimatedClusterEnergyUncertainty) < allowedVariation; + boolean energyDiffOK_antiproton = Math.abs((energyReleaseIfAntiproton - estimatedClusterEnergy)/estimatedClusterEnergyUncertainty) < allowedVariation; + boolean energyDiffOK = energyDiffOK_pion || energyDiffOK_proton || energyDiffOK_antiproton; + + //boolean fractionEnergyOK = estimatedClusterEnergy > 0.5*trackMomentumMag; // don't use + //boolean absoluteEnergyOK = (trackMomentumMag - estimatedClusterEnergy < 0.2); // deliberately one-sided (old... is this right?) + + if (m_debug) { + System.out.println("DEBUG [gen]: Checked E/P; found cluster E="+estimatedClusterEnergy + +" +- "+estimatedClusterEnergyUncertainty + +" and track E="+energyReleaseIfPion+" ("+energyReleaseIfProton+"/"+energyReleaseIfAntiproton+")" + +" => "+energyDiffOK); + System.out.println("DEBUG: Comparing track with momentum "+trackMomentumMag+" to a cluster with estimated energy "+estimatedClusterEnergy+" +- "+estimatedClusterEnergyUncertainty); + System.out.println(" If pi+: |"+energyReleaseIfPion+" - "+estimatedClusterEnergy+"|/"+estimatedClusterEnergyUncertainty+" = "+Math.abs((energyReleaseIfPion - estimatedClusterEnergy)/estimatedClusterEnergyUncertainty)+" => "+energyDiffOK_pion); + System.out.println(" If p: |"+energyReleaseIfProton+" - "+estimatedClusterEnergy+"|/"+estimatedClusterEnergyUncertainty+" = "+Math.abs((energyReleaseIfProton - estimatedClusterEnergy)/estimatedClusterEnergyUncertainty)+" => "+energyDiffOK_proton); + System.out.println(" If pbar: |"+energyReleaseIfAntiproton+" - "+estimatedClusterEnergy+"|/"+estimatedClusterEnergyUncertainty+" = "+Math.abs((energyReleaseIfAntiproton - estimatedClusterEnergy)/estimatedClusterEnergyUncertainty)+" => "+energyDiffOK_antiproton); + System.out.println(" => Overall: "+energyDiffOK); + } + + return energyDiffOK; + } + + protected List<Cluster> findNearestClusters(Hep3Vector point, List<Cluster> clusterList) + { + Map<Cluster,Double> mapClusterToDistance = new HashMap<Cluster, Double>(); + List<Cluster> sortedListOfClusters = new Vector<Cluster>(); + for (Cluster clus : clusterList) { + double dist = proximity(point, clus); + mapClusterToDistance.put(clus, new Double(dist)); + sortedListOfClusters.add(clus); + } + Comparator<Cluster> comp = new CompareMapping<Cluster>(mapClusterToDistance); + Collections.sort(sortedListOfClusters, comp); + return sortedListOfClusters; + } + protected CalorimeterHit findNearestHit(Hep3Vector point, Cluster clus) + { + CalorimeterHit nearest = null; + double minDist = 0; + for (CalorimeterHit hit : clus.getCalorimeterHits()) { + Hep3Vector hitPosition = new BasicHep3Vector(hit.getPosition()); + double distance = VecOp.sub(hitPosition, point).magnitude(); + if (distance<minDist || nearest==null) { + nearest = hit; + minDist = distance; + } + } + return nearest; + } + + protected CalorimeterHit findInnermostHitInECAL(Cluster clus) { + CalorimeterHit innermostHit = null; + for (CalorimeterHit hit : clus.getCalorimeterHits()) { + int layer = getVLayer(hit); + org.lcsim.geometry.Subdetector subdet = hit.getSubdetector(); + if ( ! subdet.isCalorimeter() ) { throw new AssertionError("Cluster hit outside calorimeter"); } + if (subdet == emb || subdet == eme) { + // EM -- OK + if (innermostHit==null || getVLayer(innermostHit)>layer) { + innermostHit = hit; + } + } + } + return innermostHit; + } + + protected double proximity(Hep3Vector point, Cluster clus) { + CalorimeterHit nearestHit = findNearestHit(point, clus); + return proximity(point, nearestHit); + } + protected double proximity(Hep3Vector point, CalorimeterHit hit) { + Hep3Vector hitPosition = new BasicHep3Vector(hit.getPosition()); + double distance = VecOp.sub(hitPosition, point).magnitude(); + return distance; + } + + protected double findUnitDotProduct(Hep3Vector tangent, Cluster clus) + { + // Find the cluster direction + BasicCluster copy = new BasicCluster(); + copy.addCluster(clus); + TensorClusterPropertyCalculator calc = new TensorClusterPropertyCalculator(); + copy.setPropertyCalculator(calc); + copy.calculateProperties(); + double[][]axes = calc.getPrincipleAxis(); + Hep3Vector clusterDir = new BasicHep3Vector(axes[0][0], axes[0][1], axes[0][2]); + // Get the dot product: + double unitDotProduct = VecOp.dot(tangent, clusterDir) / (tangent.magnitude() * clusterDir.magnitude()); + return unitDotProduct; + } + protected int getVLayer(CalorimeterHit hit) { + org.lcsim.geometry.IDDecoder id = hit.getIDDecoder(); + id.setID(hit.getCellID()); + int layer = id.getVLayer(); + return layer; + } + + protected EventHeader m_event; + public void process(EventHeader event) { + m_event = event; + initGeometry(event); + } + + public void setDebug(boolean debug) { + m_debug = debug; + } + + public void initGeometry(EventHeader event) + { + if(!m_init) + { + if(ci == null) + { + ci = CalorimeterInformation.instance(); + emb = ci.getSubdetector(CalorimeterType.EM_BARREL); + eme = ci.getSubdetector(CalorimeterType.EM_ENDCAP); + } + m_ECAL_barrel_zmin = ci.getZMin(CalorimeterType.EM_BARREL); + m_ECAL_barrel_zmax = ci.getZMax(CalorimeterType.EM_BARREL); + m_ECAL_barrel_r = emb.getLayering().getDistanceToLayerSensorMid(0); + m_ECAL_endcap_z = eme.getLayering().getDistanceToLayerSensorMid(0); + m_ECAL_endcap_rmin = ci.getRMin(CalorimeterType.EM_ENDCAP); + m_ECAL_endcap_rmax = ci.getRMax(CalorimeterType.EM_ENDCAP); + double[] zero = {0, 0, 0}; + m_fieldStrength = event.getDetector().getFieldMap().getField(zero); + m_init = true; + if (m_debug) { + System.out.println(this.getClass().getName()+": Init: ECAL barrel zmin="+m_ECAL_barrel_zmin); + System.out.println(this.getClass().getName()+": Init: ECAL barrel zmax="+m_ECAL_barrel_zmax); + System.out.println(this.getClass().getName()+": Init: ECAL barrel r="+m_ECAL_barrel_r); + System.out.println(this.getClass().getName()+": Init: ECAL endcap z="+m_ECAL_endcap_z); + System.out.println(this.getClass().getName()+": Init: ECAL endcap rmin="+m_ECAL_endcap_rmin); + System.out.println(this.getClass().getName()+": Init: ECAL endcap rmax="+m_ECAL_endcap_rmax); + } + } + } + + protected boolean m_init = false; + protected double m_ECAL_barrel_zmin; + protected double m_ECAL_barrel_zmax; + protected double m_ECAL_barrel_r; + protected double m_ECAL_endcap_z; + protected double m_ECAL_endcap_rmin; + protected double m_ECAL_endcap_rmax; + protected boolean m_debug = false; + protected double[] m_fieldStrength; + + private class CompareMapping<T> implements Comparator<T> { + public CompareMapping(Map<T,Double> map) { + m_map = map; + } + public int compare(Object o1, Object o2) { + Cluster c1 = (Cluster) o1; + Cluster c2 = (Cluster) o2; + Double D1 = m_map.get(c1); + Double D2 = m_map.get(c2); + if (D1.equals(D2)) { + // Equal + return 0; + } else if (D1.doubleValue() < D2.doubleValue()) { + return -1; + } else { + return +1; + } + } + Map<T,Double> m_map; + } + + protected ClusterEnergyCalculator m_calib = null; + protected double estimateClusterEnergy(Cluster clus) { + return m_calib.getEnergy(clus); + } + /** Specify what energy calibration to use for E/P check. */ + public void setCalibration(ClusterEnergyCalculator calib) { m_calib = calib; } + + protected double m_separationCut = 30.0; // arbitrary +}
diff -N SimpleTrackMIPClusterMatcher.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ SimpleTrackMIPClusterMatcher.java 11 Apr 2012 15:49:35 -0000 1.1 @@ -0,0 +1,72 @@
+package org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier; + +import java.util.*; +import hep.physics.vec.*; + +import org.lcsim.util.swim.HelixSwimmer; +import org.lcsim.event.Cluster; +import org.lcsim.event.CalorimeterHit; +import org.lcsim.event.Track; + +/** + * Attempt to match a Track to a MIP-like Cluster, based on the intercept point + * on the ECAL inner surface and on the direction of the track at the + * intercept point. + * + * @version $Id: SimpleTrackMIPClusterMatcher.java,v 1.1 2012/04/11 15:49:35 zaidan Exp $ + */ + +public class SimpleTrackMIPClusterMatcher extends SimpleTrackClusterMatcher +{ + protected Cluster findMatchedCluster(Track tr, HelixSwimmer swimmer, double alpha, List<Cluster> mips) + { + if (m_debug) { System.out.println("DEBUG: SimpleTrackMIPClusterMatched.findMatchedCluster() invoked for a list of "+mips.size()+" clusters."); } + + // Find the track intercept and direction + swimmer.setTrack(tr); + Hep3Vector trackPoint = swimmer.getPointAtDistance(alpha); + // Obtain the unit vector giving the tangent: + double delta = 0.1; + if (alpha < 0) { delta *= -1.0; } + Hep3Vector aLittleFurther = swimmer.getPointAtDistance(alpha+delta); + Hep3Vector tangent = VecOp.unit(VecOp.sub(aLittleFurther, trackPoint)); + + List<Cluster> nearestMIPs = findNearestClusters(trackPoint, mips); + for (Cluster nearbyMIP : nearestMIPs) { + // Obtain geometrical info: + CalorimeterHit nearestHit = findNearestHit(trackPoint, nearbyMIP); + double separation = proximity(trackPoint, nearestHit); + CalorimeterHit firstHitInECAL = findInnermostHitInECAL(nearbyMIP); + double unitDotProduct = findUnitDotProduct(tangent, nearbyMIP); + org.lcsim.geometry.Subdetector subdet = nearestHit.getSubdetector(); + // Make cuts: + boolean goodSubDet = (subdet == emb) || (subdet == eme); + boolean goodFirstLayer = (firstHitInECAL!=null && getVLayer(firstHitInECAL) < 5); + boolean goodDotProduct = (Math.abs(unitDotProduct) > 0.85); + double separationCut = m_separationCut; + boolean goodSeparation = (separation < separationCut); + boolean foundMatch = goodSubDet && goodFirstLayer && goodDotProduct && goodSeparation; + if (foundMatch) { + // OK, made a good match + if (m_debug) { System.out.println("DEBUG: Matched cluster to MIP since subdet="+subdet.getName()+" and firstlayer="+getVLayer(firstHitInECAL)+" and dotProduct="+Math.abs(unitDotProduct)+" and separation="+separation); } + return nearbyMIP; + } else { + if (m_debug) { + String printme = new String(); + printme += "Debug: Didn't match track to MIP cluster since"; + printme += " subdet="+subdet.getName()+" ["+goodSubDet+"] and"; + if (firstHitInECAL!=null) { + printme += " firstlayer="+getVLayer(firstHitInECAL)+" ["+goodFirstLayer+"] and"; + } else { + printme += " firstlayer=null ["+goodFirstLayer+"] and"; + } + printme += " dotProduct="+Math.abs(unitDotProduct)+" ["+goodDotProduct+"] and"; + printme += " separation="+separation+" ["+goodSeparation+"]"; + System.out.println(printme); + } + } + } + // No match + return null; + } +}
diff -N SmallPhotonMaker.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ SmallPhotonMaker.java 11 Apr 2012 15:49:35 -0000 1.1 @@ -0,0 +1,144 @@
+package org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier; + +import java.util.*; +import hep.physics.vec.Hep3Vector; +import hep.physics.vec.BasicHepLorentzVector; +import hep.physics.vec.HepLorentzVector; +import org.lcsim.contrib.uiowa.uiowapfa.recon.cluster.structural.FragmentIdentifier; +import org.lcsim.event.EventHeader; +import org.lcsim.event.Cluster; +import org.lcsim.event.CalorimeterHit; +import org.lcsim.event.ReconstructedParticle; +import org.lcsim.event.MCParticle; +import org.lcsim.event.SimCalorimeterHit; +import org.lcsim.event.base.BaseReconstructedParticle; +import org.lcsim.geometry.Calorimeter.CalorimeterType; +import org.lcsim.recon.util.CalorimeterInformation; +import org.lcsim.geometry.Subdetector; + +/** + * Given a list of clusters, make ones that are consistent with + * fragments AND pass photon selection into small photon clusters. + * + * Photon selection: Innermost hit is in layer 0-3 of ECAL + * + * FIXME: I think this could be implemented as a combination of a + * filter and SimpleNeutralParticleMaker without the need for a + * new class. + */ + +public class SmallPhotonMaker extends SimpleNeutralParticleMaker +{ + protected FragmentIdentifier m_fragID = null; + protected CalorimeterInformation ci; + protected Subdetector emb; + protected Subdetector eme; + public SmallPhotonMaker(FragmentIdentifier fragID) { + super(22); // make photons + m_fragID = fragID; + } + + public void process(EventHeader event) + { + m_event = event; + + // Input, output: + List<Cluster> inputClusterList = event.get(Cluster.class, m_inputClusterListName); + List<Cluster> outputClusterList = new Vector<Cluster>(); + outputClusterList.addAll(inputClusterList); // initially full + List<ReconstructedParticle> outputParticleList = new Vector<ReconstructedParticle>(); + + for (Cluster clus : inputClusterList) { + if (m_fragID.isFragment(clus, event)) { + // Small cluster/fragment -- is it photon-like? + CalorimeterHit firstHitInECAL = findInnermostHitInECAL(clus); + boolean isPhoton = (firstHitInECAL!=null && getVLayer(firstHitInECAL)<4); + if (isPhoton) { + BaseReconstructedParticle part = new BaseReconstructedParticle(); + part.addCluster(clus); + double clusterEnergy = estimateClusterEnergy(clus); + Hep3Vector threeMomentum = computeMomentum(clusterEnergy, clus); + // Set the other particle properties that are needed to render + // properly in the event display. + HepLorentzVector fourMomentum = new BasicHepLorentzVector(clusterEnergy, threeMomentum); + part.set4Vector(fourMomentum); + part.setReferencePoint(0,0,0); + part.setCharge(0); + // Add to the output list + outputParticleList.add(part); + outputClusterList.remove(clus); + } + if (m_debug) { + String printme = new String(); + printme += "DEBUG: This fragment with "; + printme += clus.getCalorimeterHits().size(); + printme += " hits has first ECAL layer "; + if (firstHitInECAL==null) { + printme += "[null]"; + } else { + printme += getVLayer(firstHitInECAL); + } + printme += " => isPhoton="+isPhoton; + printme += ". True contributions: "; + Map<MCParticle, List<CalorimeterHit>> tmpMap = new HashMap<MCParticle, List<CalorimeterHit>>(); + for (CalorimeterHit hit : clus.getCalorimeterHits()) { + SimCalorimeterHit simhit = (SimCalorimeterHit) (hit); + for (int i=0; i<simhit.getMCParticleCount(); i++) { + MCParticle hitPart = simhit.getMCParticle(i); + if ( ! (tmpMap.keySet().contains(hitPart)) ) { + tmpMap.put(hitPart, new Vector<CalorimeterHit>()); + } + tmpMap.get(hitPart).add(hit); + } + } + for (MCParticle hitPart : tmpMap.keySet()) { + printme += " "; + printme += hitPart.getType().getName(); + printme += " (E="; + printme += hitPart.getEnergy(); + printme += ", hits="; + printme += tmpMap.get(hitPart).size(); + printme += ")"; + } + System.out.println(printme); + } + } + } + + event.put(m_outputParticleListName, outputParticleList, ReconstructedParticle.class, 0); + event.put(m_outputClusterListName, outputClusterList, Cluster.class, 0); + } + + protected String m_outputClusterListName; + public void setOutputClusterList(String name) { m_outputClusterListName = name; } + + + protected CalorimeterHit findInnermostHitInECAL(Cluster clus) { + if(ci == null) + { + ci = CalorimeterInformation.instance(); + emb = ci.getSubdetector(CalorimeterType.EM_BARREL); + eme = ci.getSubdetector(CalorimeterType.EM_ENDCAP); + } + CalorimeterHit innermostHit = null; + for (CalorimeterHit hit : clus.getCalorimeterHits()) { + int layer = getVLayer(hit); + Subdetector subdet = hit.getSubdetector(); + if ( ! subdet.isCalorimeter() ) { throw new AssertionError("Cluster hit outside calorimeter"); } + if (subdet == eme || subdet == emb) { + // EM -- OK + if (innermostHit==null || getVLayer(innermostHit)>layer) { + innermostHit = hit; + } + } + } + return innermostHit; + } + + protected int getVLayer(CalorimeterHit hit) { + org.lcsim.geometry.IDDecoder id = hit.getIDDecoder(); + id.setID(hit.getCellID()); + int layer = id.getVLayer(); + return layer; + } +}
diff -N TrackClusterMatcher.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ TrackClusterMatcher.java 11 Apr 2012 15:49:35 -0000 1.1 @@ -0,0 +1,26 @@
+package org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier; + +import java.util.*; +import org.lcsim.event.Cluster; +import org.lcsim.event.Track; + +/** + * Interface for matching Tracks to Clusters + * + * @version $Id: TrackClusterMatcher.java,v 1.1 2012/04/11 15:49:35 zaidan Exp $ + */ + +public interface TrackClusterMatcher +{ + /** + * Attempt to match a Track <code>tr</code> to a Cluster + * from the list <code>clusters</code>. The return value + * is the matched Cluster, or null if there is no acceptable + * match found. + * + * Implementations typically return a cluster from the list supplied. + * They may also return a new cluster which contains clusters + * (via Cluster.getClusters()) from this list (and no other hits/clusters). + */ + public Cluster matchTrackToCluster(Track tr, List<Cluster> clusters); +}
diff -N TrackHelixExtrapolator.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ TrackHelixExtrapolator.java 11 Apr 2012 15:49:35 -0000 1.1 @@ -0,0 +1,232 @@
+package org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier; + +import java.util.*; +import hep.physics.vec.*; +import org.lcsim.util.swim.HelixSwimmer; +import org.lcsim.event.EventHeader; +import org.lcsim.event.Track; + +public class TrackHelixExtrapolator extends HelixExtrapolator +{ + protected Hep3Vector m_intercept = null; + protected HelixSwimmer m_swimmer = null; + protected double m_alphaIntercept = Double.NaN; + + public TrackHelixExtrapolator() { + super(); + } + + protected TrackHelixExtrapolator(TrackHelixExtrapolator old) { + super(old); + if (old.m_intercept != null) { + m_intercept = new BasicHep3Vector(old.m_intercept.x(), old.m_intercept.y(), old.m_intercept.z()); + } else { + m_intercept = null; + } + m_swimmer = old.m_swimmer; // Safe, since any change to track will create a new HelixSwimmer. + m_alphaIntercept = old.m_alphaIntercept; + } + + public void process(EventHeader event) { + super.process(event); + } + + protected Hep3Vector getInterceptPoint() { + return new BasicHep3Vector(m_intercept.x(), m_intercept.y(), m_intercept.z()); + } + public HelixExtrapolationResult performExtrapolation(Track tr) { + m_track = tr; + // Null track means we blank everything and return failure. + if (tr == null) { + m_intercept = null; + m_swimmer = null; + m_alphaIntercept = Double.NaN; + return null; + } + + // Make a HelixSwimmer to propagate the track + m_swimmer = new HelixSwimmer(m_fieldStrength[2]); + m_swimmer.setTrack(tr); + + // Try swimming to the barrel: + double alphaBarrel = swimToBarrel(m_swimmer); + boolean validBarrel = false; + // Try swimming to the endcap: + double alphaEndcap = swimToEndcap(m_swimmer); + boolean validEndcap = false; + + // Get helix fit output + m_alphaIntercept = Double.NaN; + if (isValidBarrelIntercept(m_swimmer, alphaBarrel, m_cutSeparation)) { + validBarrel = true; + } + if (isValidEndcapIntercept(m_swimmer, alphaEndcap, m_cutSeparation)) { + validEndcap = true; + } + + // Check for special case in corner of barrel/endcap overlap region + if ( validEndcap && validBarrel ) { + // Both apparently valid... check again + boolean tightValidEndcap = isValidEndcapIntercept(m_swimmer, alphaEndcap, 0.0); + boolean tightValidBarrel = isValidBarrelIntercept(m_swimmer, alphaBarrel, 0.0); + if (tightValidEndcap && tightValidBarrel) { + // This can happen if the track has moderate pT -- it goes into the + // barrel, spirals out again, and eventually hits the endcap. + // If this is what happened then it should reach the barrel first. + if (alphaEndcap < alphaBarrel) { + Hep3Vector interceptEndcap = m_swimmer.getPointAtDistance(alphaEndcap); + Hep3Vector interceptBarrel = m_swimmer.getPointAtDistance(alphaBarrel); + double rEndcap = Math.sqrt(interceptEndcap.x()*interceptEndcap.x() + interceptEndcap.y()*interceptEndcap.y()); + double rBarrel = Math.sqrt(interceptBarrel.x()*interceptBarrel.x() + interceptBarrel.y()*interceptBarrel.y()); + double zEndcap = interceptEndcap.z(); + double zBarrel = interceptBarrel.z(); + System.out.println(this.getClass().getName()+": Track extrapolation failure: Track hits endcap THEN barrel -- this doesn't make sense!"); + System.out.println(" Endcap intercept at alpha="+alphaEndcap+" has r="+rEndcap+", z="+zEndcap); + System.out.println(" Barrel intercept at alpha="+alphaBarrel+" has r="+rBarrel+", z="+zBarrel); + Hep3Vector p3 = new BasicHep3Vector(tr.getMomentum()); + double p = p3.magnitude(); + double pt = Math.sqrt(p3.x()*p3.x() + p3.y()*p3.y()); + System.out.println(" Track has p="+p+" and pt="+pt); + validEndcap = validBarrel = false; + m_intercept = null; + m_swimmer = null; + m_alphaIntercept = Double.NaN; + return null; + } else { + validEndcap = false; + } + } else if (!tightValidEndcap && !tightValidBarrel) { + throw new AssertionError("Invalid state"); + } else { + // Only one valid solution -- OK + validEndcap = tightValidEndcap; + validBarrel = tightValidBarrel; + } + } + + if (validEndcap) { m_alphaIntercept = alphaEndcap; } + if (validBarrel) { m_alphaIntercept = alphaBarrel; } + + // Did we make a successful extrapolation? + if ( Double.isNaN(m_alphaIntercept)) { + // No -- extrapolation failed + if (m_debug) { System.out.println("DEBUG: "+this.getClass().getName()+" failed to extrapolate: alpha is NaN"); } + return null; + } else if ( !(validEndcap || validBarrel) ) { + // Invalid state + if (m_debug) { System.out.println("DEBUG: "+this.getClass().getName()+" failed to extrapolate: not a valid barrel or endcap point"); } + return null; + } else if ( validEndcap && validBarrel ) { + // Invalid state + if (m_debug) { System.out.println("DEBUG: "+this.getClass().getName()+" failed to extrapolate: valid barrel AND endcap point"); } + throw new AssertionError("DEBUG: "+this.getClass().getName()+" failed to extrapolate: valid barrel AND endcap point"); + } else { + // Extrapolation succeeded. + m_intercept = m_swimmer.getPointAtDistance(m_alphaIntercept); + m_barrelValid = validBarrel; + m_endcapValid = validEndcap; + + if (m_debug) { + System.out.print("DEBUG: "+this.getClass().getName()+" extrapolated OK. validEndcap="+validEndcap+" and validBarrel="+validBarrel+" and m_alphaIntercept="+m_alphaIntercept); + if (m_intercept == null) { + System.out.print(" -- but intercept point is null!"); + } else { + double r = Math.sqrt(m_intercept.x()*m_intercept.x() + m_intercept.y()*m_intercept.y()); + System.out.print(" -- intercept point at r="+r+", z="+m_intercept.z()); + } + System.out.println(); + } + + // Output + HelixExtrapolationResult output = new HelixExtrapolationResult(new TrackHelixExtrapolator(this)); + return output; + } + } + protected Hep3Vector getTangent() { + return VecOp.unit(m_swimmer.getMomentumAtLength(m_alphaIntercept)); + } + protected Hep3Vector getTangent(Hep3Vector v) { + double alphaPoint = m_swimmer.getDistanceToPoint(v); + return VecOp.unit(m_swimmer.getMomentumAtLength(alphaPoint)); + } + protected Hep3Vector extendToEndcapLayer(int layer, Vector<Double> endcap_layering_z, double endcap_rmin, double endcap_rmax, int nsides ) { + double layer_z = Math.abs(endcap_layering_z.get(layer)); + double distanceToEndcap = m_swimmer.getDistanceToZ( layer_z); + + Hep3Vector v = m_swimmer.getPointAtDistance(distanceToEndcap); + double found_endcap_polar_r = Math.sqrt(v.x()*v.x() + v.y()*v.y()); + boolean validSolution = (found_endcap_polar_r >= endcap_rmin-m_cutSeparation && found_endcap_polar_r <= endcap_rmax+m_cutSeparation); + if(validSolution){ + return v; + } else { + return null; + } + } + protected Hep3Vector extendToBarrelLayer(int layer, Vector<Double> barrel_layering_r, double barrel_zmin, double barrel_zmax, int nsides ) { + double layer_r = barrel_layering_r.get(layer); + double distance; + if(nsides < 3)distance = m_swimmer.getDistanceToRadius(layer_r); + else distance = m_swimmer.getDistanceToPolyhedra(layer_r,nsides); + + Hep3Vector v = m_swimmer.getPointAtDistance(distance); + double found_barrel_z = v.z(); + boolean validSolution =(found_barrel_z >= barrel_zmin-m_cutSeparation && found_barrel_z <= barrel_zmax+m_cutSeparation); + if (!Double.isNaN(distance) && validSolution) { + // Extrapolated OK + return v; + } else { + // Extrapolation failed + return null; + } + } + + // Internal stuff + protected double swimToBarrel(HelixSwimmer swimmer) { + // Look for a hit in the first layer of the ECAL barrel + if(m_ECAL_barrel_nsides < 3)return swimmer.getDistanceToRadius(m_ECAL_barrel_r); + return swimmer.getDistanceToPolyhedra(m_ECAL_barrel_r,m_ECAL_barrel_nsides); + } + protected double swimToEndcap(HelixSwimmer swimmer) { + // Look for a hit in the first layer of the ECAL endcap + double distanceToEndcap1 = swimmer.getDistanceToZ(m_ECAL_endcap_z); + double distanceToEndcap2 = swimmer.getDistanceToZ(-m_ECAL_endcap_z); + if (distanceToEndcap1>0) { + return distanceToEndcap1; + } else if (distanceToEndcap2>0) { + return distanceToEndcap2; + } else { + return Double.NaN; + } + } + protected boolean isValidBarrelIntercept(HelixSwimmer swimmer, double alpha, double uncertainty) { + // OLD: // Must have -m_ECAL_barrel_z <= z <= +m_ECAL_barrel_z (within errors) + // NEW: // Above AND must have -m_ECAL_endcap_z <= z <= m_ECAL_endcap_z + //double uncertainty = m_cutSeparation; + Hep3Vector intercept = swimmer.getPointAtDistance(alpha); + double z = intercept.z(); + boolean zInRangeBarrel = (z >= m_ECAL_barrel_zmin-uncertainty && z <= m_ECAL_barrel_zmax+uncertainty); + boolean vetoEndcap = (z >= -m_ECAL_endcap_z && z <= m_ECAL_endcap_z); + return zInRangeBarrel && vetoEndcap; + } + protected boolean isValidEndcapIntercept(HelixSwimmer swimmer, double alpha, double uncertainty) { + // Must have m_ECAL_endcap_rmin <= r <= m_ECAL_endcap_rmax (within errors) + //double uncertainty = m_cutSeparation; + Hep3Vector intercept = swimmer.getPointAtDistance(alpha); + double r = Math.sqrt(intercept.x()*intercept.x() + intercept.y()*intercept.y()); + if(m_ECAL_endcap_nsides > 2) + { + double phi = Math.atan2(intercept.y(),intercept.x()); + double phip = phi; + while(phip < -Math.PI/m_ECAL_endcap_nsides){phip += 2.*Math.PI/m_ECAL_endcap_nsides;} + while(phip >= Math.PI/m_ECAL_endcap_nsides){phip -= 2.*Math.PI/m_ECAL_endcap_nsides;} + double x = r*Math.cos(phip); + boolean rInRange = (x >= m_ECAL_endcap_rmin-uncertainty && x <= m_ECAL_endcap_rmax+uncertainty); + return rInRange; + } + else + { + boolean rInRange = (r >= m_ECAL_endcap_rmin-uncertainty && r <= m_ECAL_endcap_rmax+uncertainty); + return rInRange; + } + } +}
diff -N TrackHelixPlusHitExtrapolator.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ TrackHelixPlusHitExtrapolator.java 11 Apr 2012 15:49:35 -0000 1.1 @@ -0,0 +1,348 @@
+package org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier; + +import java.util.*; +import hep.physics.vec.*; + +import org.lcsim.event.TrackerHit; +import org.lcsim.event.EventHeader; +import org.lcsim.util.swim.HelixSwimmer; +import org.lcsim.event.Track; + +public class TrackHelixPlusHitExtrapolator extends TrackHelixExtrapolator +{ + public TrackHelixPlusHitExtrapolator() { + super(); + } + + protected TrackHelixPlusHitExtrapolator(TrackHelixPlusHitExtrapolator old) { + super(old); + } + + public void process(EventHeader event) { + super.process(event); + } + + public HelixExtrapolationResult performExtrapolation(Track tr) { + // Null track means we blank everything and return failure. + m_track = tr; + if (tr == null) { + m_intercept = null; + m_swimmer = null; + m_alphaIntercept = Double.NaN; + return null; + } + + // Start by swimming as per parent: + super.performExtrapolation(tr); + if (m_swimmer == null) { + // Failed to extrapolate completely -- didn't even fit a helix + m_intercept = null; + m_swimmer = null; + m_alphaIntercept = Double.NaN; + return null; + } + + // Now scan over tracker hits and find the outermost one. + // Note that the details here depend on what kind of hit + // we're looking at. + List<TrackerHit> trackHits = tr.getTrackerHits(); + if (trackHits.size() == 0) { throw new AssertionError("Track found with no track hits!"); } + TrackerHit outermostHit = findOutermostHit(trackHits); + + // Find the POCA to the hit with the old helix: + double alpha = Double.NaN; + Hep3Vector pointOfClosestApproachToTrackHit = null; + Hep3Vector offset = null; + + if (outermostHit instanceof org.lcsim.event.base.BaseTrackerHitMC) { + // This cheated hit has exact 3D info + Hep3Vector positionOfOutermostHit = new BasicHep3Vector(outermostHit.getPosition()); + alpha = m_swimmer.getTrackLengthToPoint(positionOfOutermostHit); + pointOfClosestApproachToTrackHit = m_swimmer.getPointAtLength(alpha); + // Correct with a 3D step from POCA-to-hit to the hit itself. + offset = VecOp.sub(positionOfOutermostHit, pointOfClosestApproachToTrackHit); + } else if (outermostHit instanceof org.lcsim.fit.helicaltrack.HelicalTrack2DHit) { + // This is a barrel hit with 2D hit info (and a weak constraint on z) + // Correct with an offset in r-phi but not in z + org.lcsim.fit.helicaltrack.HelicalTrack2DHit hit = (org.lcsim.fit.helicaltrack.HelicalTrack2DHit)(outermostHit); + double r = hit.r(); + alpha = m_swimmer.getDistanceToRadius(r); + pointOfClosestApproachToTrackHit = m_swimmer.getPointAtLength(alpha); + // Correct in xy but not in z since no z information + offset = new BasicHep3Vector(hit.x() - pointOfClosestApproachToTrackHit.x(), hit.y() - pointOfClosestApproachToTrackHit.y(), 0.0); + } else if (outermostHit instanceof org.lcsim.fit.helicaltrack.HelicalTrackCross) { + // This is an endcap hit with hit info from axial+stereo strips. + // Uncertainty is ambiguous somehow -- unclear... + org.lcsim.fit.helicaltrack.HelicalTrackCross hit = (org.lcsim.fit.helicaltrack.HelicalTrackCross)(outermostHit); + double z = hit.z(); + alpha = m_swimmer.getDistanceToZ(z); + pointOfClosestApproachToTrackHit = m_swimmer.getPointAtLength(alpha); + // Step from extrapolation point (x, y, z) to hit position (x', y', z) -- note that both have same z. + offset = new BasicHep3Vector(hit.x() - pointOfClosestApproachToTrackHit.x(), hit.y() - pointOfClosestApproachToTrackHit.y(), 0.0); + } else if (outermostHit instanceof org.lcsim.fit.helicaltrack.HelicalTrack3DHit) { + // This is a vertex detector hit with 3D hit info + org.lcsim.fit.helicaltrack.HelicalTrack3DHit hit = (org.lcsim.fit.helicaltrack.HelicalTrack3DHit)(outermostHit); + Hep3Vector positionOfOutermostHit = new BasicHep3Vector(hit.x(), hit.y(), hit.z()); + alpha = m_swimmer.getTrackLengthToPoint(positionOfOutermostHit); + pointOfClosestApproachToTrackHit = m_swimmer.getPointAtLength(alpha); + // Correct with a 3D step from POCA-to-hit to the hit itself. + offset = VecOp.sub(positionOfOutermostHit, pointOfClosestApproachToTrackHit); + } else { + // Unknown! + Hep3Vector positionOfOutermostHit = new BasicHep3Vector(outermostHit.getPosition()); + double r = Math.sqrt(positionOfOutermostHit.x()*positionOfOutermostHit.x() + positionOfOutermostHit.y()*positionOfOutermostHit.y()); + double z = positionOfOutermostHit.z(); + throw new AssertionError("ERROR: Unknown hit of type "+outermostHit.getClass().getName()+" at r="+r+", z="+z); + } + + Hep3Vector momentumAtPOCA = m_swimmer.getMomentumAtLength(alpha); + Hep3Vector newPoint = VecOp.add(pointOfClosestApproachToTrackHit, offset); + + // Make a new helix swimmer: + HelixSwimmer newHelix = new HelixSwimmer(m_fieldStrength[2]); + newHelix.setTrack(momentumAtPOCA, newPoint, tr.getCharge()); + // Over-write old helix swimmer: + m_swimmer = newHelix; + + // Try swimming to the barrel: + double alphaBarrel = swimToBarrel(m_swimmer); + boolean validBarrel = false; + // Try swimming to the endcap: + double alphaEndcap = swimToEndcap(m_swimmer); + boolean validEndcap = false; + + // Get helix fit output + m_alphaIntercept = Double.NaN; + m_intercept = null; + if (isValidBarrelIntercept(m_swimmer, alphaBarrel, m_cutSeparation)) { + validBarrel = true; + } + if (isValidEndcapIntercept(m_swimmer, alphaEndcap, m_cutSeparation)) { + validEndcap = true; + } + + // Check for special case in corner of barrel/endcap overlap region + if ( validEndcap && validBarrel ) { + // Both apparently valid... check again + boolean tightValidEndcap = isValidEndcapIntercept(m_swimmer, alphaEndcap, 0.0); + boolean tightValidBarrel = isValidBarrelIntercept(m_swimmer, alphaBarrel, 0.0); + if (tightValidEndcap && tightValidBarrel) { + // This can happen if the track has moderate pT -- it goes into the + // barrel, spirals out again, and eventually hits the endcap. + // If this is what happened then it should reach the barrel first. + if (alphaEndcap < alphaBarrel) { + Hep3Vector interceptEndcap = m_swimmer.getPointAtDistance(alphaEndcap); + Hep3Vector interceptBarrel = m_swimmer.getPointAtDistance(alphaBarrel); + double rEndcap = Math.sqrt(interceptEndcap.x()*interceptEndcap.x() + interceptEndcap.y()*interceptEndcap.y()); + double rBarrel = Math.sqrt(interceptBarrel.x()*interceptBarrel.x() + interceptBarrel.y()*interceptBarrel.y()); + double zEndcap = interceptEndcap.z(); + double zBarrel = interceptBarrel.z(); + throw new AssertionError("Track hits endcap THEN barrel -- this doesn't make sense!\nEndcap intercept at alpha="+alphaEndcap+" has r="+rEndcap+", z="+zEndcap+"\nBarrel intercept at alpha="+alphaBarrel+" has r="+rBarrel+", z="+zBarrel); + } else { + validEndcap = false; + } + } else if (!tightValidEndcap && !tightValidBarrel) { + throw new AssertionError("Invalid state"); + } else { + // Only one valid solution -- OK + validEndcap = tightValidEndcap; + validBarrel = tightValidBarrel; + } + } + + if (validEndcap) { m_alphaIntercept = alphaEndcap; } + if (validBarrel) { m_alphaIntercept = alphaBarrel; } + + // Did we make a successful extrapolation? + if ( Double.isNaN(m_alphaIntercept)) { + // No -- extrapolation failed + if (m_debug) { System.out.println("DEBUG: "+this.getClass().getName()+" failed to extrapolate: alpha is NaN"); } + return null; + } else if ( !(validEndcap || validBarrel) ) { + // Invalid state + if (m_debug) { System.out.println("DEBUG: "+this.getClass().getName()+" failed to extrapolate: not a valid barrel or endcap point"); } + return null; + } else if ( validEndcap && validBarrel ) { + // Invalid state + if (m_debug) { System.out.println("DEBUG: "+this.getClass().getName()+" failed to extrapolate: valid barrel AND endcap point"); } + throw new AssertionError("DEBUG: "+this.getClass().getName()+" failed to extrapolate: valid barrel AND endcap point"); + //return null; + } else { + // Extrapolation succeeded. + m_intercept = m_swimmer.getPointAtDistance(m_alphaIntercept); + m_barrelValid = validBarrel; + m_endcapValid = validEndcap; + if (m_debug) { + System.out.print("DEBUG: "+this.getClass().getName()+" extrapolated OK. validEndcap="+validEndcap+" and validBarrel="+validBarrel+" and m_alphaIntercept="+m_alphaIntercept); + if (m_intercept == null) { + System.out.print(" -- but intercept point is null!"); + } else { + double r = Math.sqrt(m_intercept.x()*m_intercept.x() + m_intercept.y()*m_intercept.y()); + System.out.print(" -- intercept point at r="+r+", z="+m_intercept.z()); + } + System.out.println(); + } + // Output + HelixExtrapolationResult output = new HelixExtrapolationResult(new TrackHelixPlusHitExtrapolator(this)); + return output; + } + } + + TrackerHit findOutermostHit(List<TrackerHit> trackerHits) { + boolean cheatHitFound = false; + boolean helicalHitFound = false; + for (TrackerHit hit : trackerHits) { + boolean thisHitIsCheatHit = (hit instanceof org.lcsim.event.base.BaseTrackerHitMC); + boolean thisHitIsHelicalHit = (hit instanceof org.lcsim.fit.helicaltrack.HelicalTrackCross || hit instanceof org.lcsim.fit.helicaltrack.HelicalTrack2DHit || hit instanceof org.lcsim.fit.helicaltrack.HelicalTrack3DHit); + if (thisHitIsCheatHit && thisHitIsHelicalHit) { + throw new AssertionError("Ambiguous hit of class "+hit.getClass().getName()); + } else if (!thisHitIsCheatHit && !thisHitIsHelicalHit) { + throw new AssertionError("Unidentified hit of unknown class "+hit.getClass().getName()); + } + if (thisHitIsCheatHit) { + cheatHitFound = true; + } + if (thisHitIsHelicalHit) { + helicalHitFound = true; + } + } + if (cheatHitFound && helicalHitFound) { + throw new AssertionError("Mixed list of hits!"); + } + if (cheatHitFound) { + return findOutermostCheatHit(trackerHits); + } else if (helicalHitFound) { + return findOutermostHelicalHit(trackerHits); + } else { + throw new AssertionError("Unclassified list of hits!"); + } + } + + TrackerHit findOutermostCheatHit(List<TrackerHit> trackerHits) { + // Find hit with outermost Z + TrackerHit outermostHit = null; + Hep3Vector positionOfOutermostHit = null; + for (TrackerHit trackHit : trackerHits) { + Hep3Vector pos = new BasicHep3Vector(trackHit.getPosition()); + if (outermostHit==null) { + outermostHit = trackHit; + positionOfOutermostHit = pos; + } else { + if (Math.abs(pos.z()) > Math.abs(positionOfOutermostHit.z())) { + outermostHit = trackHit; + positionOfOutermostHit = pos; + } + } + } + return outermostHit; + } + + TrackerHit findOutermostHelicalHit(List<TrackerHit> trackerHits) { + // This is a little tricky. The rules are: + // 1) Any outer tracker layer > any vertex detector layer + // 2) For two vertex detector hits, the one with the larger |z| wins. + // 3) For any two outer tracker barrel layers, the one with the larger r wins. + // 4) For any two outer tracker endcap layers, the one with the larger |z| wins. + // 5) For a tracker barrel & endcap layer... + // 5a) If barrel |zmin| > endcap |z|, the barrel wins + // 5b) If barrel |zmax| < endcap |z|, the endcap wins + // 5c) If there is ambiguity, the barrel wins (a little arbitrary) + TrackerHit outermostHit = null; + for (TrackerHit hit : trackerHits) { + if (outermostHit == null) { + outermostHit = hit; + } else { + boolean outermostHitIsVertexHit = (outermostHit instanceof org.lcsim.fit.helicaltrack.HelicalTrack3DHit); + boolean outermostHitIsBarrelHit = (outermostHit instanceof org.lcsim.fit.helicaltrack.HelicalTrack2DHit); + boolean outermostHitIsEndcapHit = (outermostHit instanceof org.lcsim.fit.helicaltrack.HelicalTrackCross); + if (!(outermostHitIsVertexHit || outermostHitIsBarrelHit || outermostHitIsEndcapHit)) { throw new AssertionError("Unidentified hit"); } + if (outermostHitIsVertexHit && outermostHitIsBarrelHit) { throw new AssertionError("Ambiguous hit"); } + if (outermostHitIsVertexHit && outermostHitIsEndcapHit) { throw new AssertionError("Ambiguous hit"); } + if (outermostHitIsBarrelHit && outermostHitIsEndcapHit) { throw new AssertionError("Ambiguous hit"); } + boolean currentHitIsVertexHit = (hit instanceof org.lcsim.fit.helicaltrack.HelicalTrack3DHit); + boolean currentHitIsBarrelHit = (hit instanceof org.lcsim.fit.helicaltrack.HelicalTrack2DHit); + boolean currentHitIsEndcapHit = (hit instanceof org.lcsim.fit.helicaltrack.HelicalTrackCross); + if (!(currentHitIsVertexHit || currentHitIsBarrelHit || currentHitIsEndcapHit)) { throw new AssertionError("Unidentified hit"); } + if (currentHitIsVertexHit && currentHitIsBarrelHit) { throw new AssertionError("Ambiguous hit"); } + if (currentHitIsVertexHit && currentHitIsEndcapHit) { throw new AssertionError("Ambiguous hit"); } + if (currentHitIsBarrelHit && currentHitIsEndcapHit) { throw new AssertionError("Ambiguous hit"); } + + if (currentHitIsVertexHit) { + if (outermostHitIsVertexHit) { + // 2) For two vertex detector hits, the one with the larger |z| wins. + double currentHit_z = Math.abs(((org.lcsim.fit.helicaltrack.HelicalTrack3DHit)(hit)).z()); + double outermostHit_z = Math.abs(((org.lcsim.fit.helicaltrack.HelicalTrack3DHit)(outermostHit)).z()); + if (currentHit_z > outermostHit_z) { + outermostHit = hit; + } + continue; + } else { + // 1) Any outer tracker layer > any vertex detector layer + continue; + } + } else { + if (outermostHitIsVertexHit) { + // 1) Any outer tracker layer > any vertex detector layer + outermostHit = hit; + continue; + } else { + if (outermostHitIsBarrelHit && currentHitIsBarrelHit) { + // 3) For any two outer tracker barrel layers, the one with the larger r wins. + double currentHit_r = ((org.lcsim.fit.helicaltrack.HelicalTrack2DHit)(hit)).r(); + double outermostHit_r = ((org.lcsim.fit.helicaltrack.HelicalTrack2DHit)(outermostHit)).r(); + if (currentHit_r > outermostHit_r) { + outermostHit = hit; + } + continue; + } else if (outermostHitIsEndcapHit && currentHitIsEndcapHit) { + // 4) For any two outer tracker endcap layers, the one with the larger |z| wins. + double currentHit_z = Math.abs(((org.lcsim.fit.helicaltrack.HelicalTrackCross)(hit)).z()); + double outermostHit_z = Math.abs(((org.lcsim.fit.helicaltrack.HelicalTrackCross)(outermostHit)).z()); + if (currentHit_z > outermostHit_z) { + outermostHit = hit; + } + continue; + } else if (outermostHitIsBarrelHit && currentHitIsEndcapHit) { + // One barrel and one endcap layer + double barrel_zmin = Math.abs(((org.lcsim.fit.helicaltrack.HelicalTrack2DHit)(outermostHit)).zmin()); + double barrel_zmax = Math.abs(((org.lcsim.fit.helicaltrack.HelicalTrack2DHit)(outermostHit)).zmax()); + double endcap_z = Math.abs(((org.lcsim.fit.helicaltrack.HelicalTrackCross)(hit)).z()); + if (barrel_zmin > endcap_z) { + // 5a) If barrel |zmin| > endcap |z|, the barrel wins + continue; + } else if (barrel_zmax < endcap_z) { + // 5b) If barrel |zmax| < endcap |z|, the endcap wins + outermostHit = hit; + continue; + } else { + // 5c) If there is ambiguity, the barrel wins (a little arbitrary) + continue; + } + } else if (outermostHitIsEndcapHit&¤tHitIsBarrelHit) { + // One barrel and one endcap layer + double barrel_zmin = Math.abs(((org.lcsim.fit.helicaltrack.HelicalTrack2DHit)(hit)).zmin()); + double barrel_zmax = Math.abs(((org.lcsim.fit.helicaltrack.HelicalTrack2DHit)(hit)).zmax()); + double endcap_z = Math.abs(((org.lcsim.fit.helicaltrack.HelicalTrackCross)(outermostHit)).z()); + if (barrel_zmin > endcap_z) { + // 5a) If barrel |zmin| > endcap |z|, the barrel wins + outermostHit = hit; + continue; + } else if (barrel_zmax < endcap_z) { + // 5b) If barrel |zmax| < endcap |z|, the endcap wins + continue; + } else { + // 5c) If there is ambiguity, the barrel wins (a little arbitrary) + outermostHit = hit; + continue; + } + } + } + } + // Shouldn't reach here + throw new AssertionError("Failed to classify! outermostHit is "+outermostHit.getClass().getName()+" and hit is "+hit.getClass().getName()); + } + } + + return outermostHit; + } +}
diff -N TrackToClusterMapMaker.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ TrackToClusterMapMaker.java 11 Apr 2012 15:49:35 -0000 1.1 @@ -0,0 +1,53 @@
+package org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier; + +import java.util.*; +import org.lcsim.util.*; +import org.lcsim.event.*; +import org.lcsim.event.util.*; + +/** + * Abstract class with several implementations, used for + * matching tracks to clusters. The rules are: + * 1) The input tracks are supplied as a named List from the event. + * 2) Matched tracks are written out to the event as a Map<Track,Cluster> + * 3) Unmatched tracks are written out to the event as a List<Track> + * 4) The output tracks MAY be altered copies of the input tracks. + * For example, if two tracks enter the calorimeter in the same + * cell, they may get bundled into a single track. So the user + * should not re-use the input track list. + * 5) There should be no overlap between the matched tracks and the + * unmatched tracks. + * 6) Implementing classes MAY write out additional output. + * + * @version $Id: TrackToClusterMapMaker.java,v 1.1 2012/04/11 15:49:35 zaidan Exp $ + * @author [log in to unmask] + */ + +public abstract class TrackToClusterMapMaker extends Driver { + + abstract protected Map<Track,Cluster> makeMap(EventHeader event); + + protected String m_inputTrackListName; + protected String m_outputMapName; + protected String m_outputUnmatchedTrackListName; + + /** + * General-purpose constructor. Implementing classes may make their + * own constructor with additional arguments. + * + * @param inputTrackList The name of the input List of Tracks to read in from the event and match to clusters. + * @param outputMap The name to write out the output Map<Track,Cluster> of matched tracks as. + * @param outputUnmatchedTrackList The name to write unmatched/unused tracks out as. + */ + public TrackToClusterMapMaker(String inputTrackList, String outputMap, String outputUnmatchedTrackList) { + super(); + m_inputTrackListName = inputTrackList; + m_outputMapName = outputMap; + m_outputUnmatchedTrackListName = outputUnmatchedTrackList; + } + + public void process(EventHeader event) { + Map<Track,Cluster> output = makeMap(event); + event.put(m_outputMapName, output); + } +}
diff -N TrackToElectronMapMaker.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ TrackToElectronMapMaker.java 11 Apr 2012 15:49:35 -0000 1.1 @@ -0,0 +1,165 @@
+package org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier; + +import java.util.*; +import hep.physics.vec.*; +import org.lcsim.event.*; +import org.lcsim.recon.cluster.util.*; +import org.lcsim.util.swim.Line; +import org.lcsim.recon.util.CalorimeterInformation; +import org.lcsim.geometry.Calorimeter.CalorimeterType; + +/** + * Try to make electrons. + * + * @version $Id: TrackToElectronMapMaker.java,v 1.1 2012/04/11 15:49:35 zaidan Exp $ + * @author [log in to unmask] + */ + +public class TrackToElectronMapMaker extends TrackToClusterMapMaker { + + protected String m_outputElectronClusterListName; + protected String m_inputPhotonListName; + protected ClusterEnergyCalculator m_photonCalib; + protected HelixExtrapolator m_findCluster; + protected CalorimeterInformation ci; + + public TrackToElectronMapMaker(HelixExtrapolator findCluster, String inputPhotonList, String inputTrackList, String outputTrackClusterMap, String outputUnmatchedTrackList, String outputElectronClusterList) { + super(inputTrackList, outputTrackClusterMap, outputUnmatchedTrackList); + m_outputElectronClusterListName = outputElectronClusterList; + m_inputPhotonListName = inputPhotonList; + m_findCluster = findCluster; + m_photonCalib = new QPhotonClusterEnergyCalculator(); + } + + + + protected Map<Track,Cluster> makeMap(EventHeader event) { + // Read in inputs + if(ci == null)ci = CalorimeterInformation.instance(); + List<Track> trackList = event.get(Track.class, m_inputTrackListName); + List<Cluster> photons = event.get(Cluster.class, m_inputPhotonListName); + + // The output + Map<Track,Cluster> outputMap = new HashMap<Track,Cluster>(); + + // Extrapolation utility + LocalHelixExtrapolationTrackClusterMatcher genMatch = new LocalHelixExtrapolationTrackClusterMatcher(m_findCluster); + + // Loop over tracks, looking for a good match to a photon + Map<Track,Cluster> electronCandidateMap = new HashMap<Track,Cluster>(); + Set<Cluster> electronCandidateClusters = new HashSet<Cluster>(); + Set<Cluster> vetoedElectronCandidateClusters = new HashSet<Cluster>(); + List<Cluster> electronClusters = new Vector<Cluster>(); + List<Track> electronTracks = new Vector<Track>(); + for (Track tr : trackList) { + Cluster matchedCluster = genMatch.matchTrackToCluster(tr, photons); + if (matchedCluster != null) { + if (photons.contains(matchedCluster)) { + // Electron candidate + if (electronCandidateClusters.contains(matchedCluster)) { + // Multiple track matches => veto + vetoedElectronCandidateClusters.add(matchedCluster); + } + electronCandidateClusters.add(matchedCluster); + // Now, are we confident that it's an electron? + double electronResid = electronEnergyNormalizedResidual(tr, matchedCluster); + int hitsInCore = countHitsInCoreInFirstLayers(tr, matchedCluster, 5); + double trackIP = distanceFromTrackToPhotonCore(tr, matchedCluster); + if (electronResid > -2.0 && electronResid < 2.0 && trackIP < 7.0 && hitsInCore > 1) { + // Accept as electron + electronCandidateMap.put(tr, matchedCluster); + } + } else { + throw new AssertionError("Internal consistency failure"); + } + } + } + + // Now, did we accept any of those? + for (Track tr : electronCandidateMap.keySet()) { + Cluster clus = electronCandidateMap.get(tr); + if (!electronCandidateClusters.contains(clus)) { throw new AssertionError("Book-keeping failure"); } + if (!vetoedElectronCandidateClusters.contains(clus)) { + // We accepted it and didn't veto it => electron + if (electronClusters.contains(clus)) { throw new AssertionError("Book-keeping failure"); } + electronClusters.add(clus); + electronTracks.add(tr); + outputMap.put(tr,clus); + } + } + + // Unmatched tracks + List<Track> unmatchedTracks = new Vector<Track>(); + unmatchedTracks.addAll(trackList); + unmatchedTracks.removeAll(electronTracks); + + // Outputs + event.put(m_outputUnmatchedTrackListName, unmatchedTracks); + event.put(m_outputElectronClusterListName, electronClusters); + return outputMap; + } + + // Utility routines + + private double electronEnergyNormalizedResidual(Track tr, Cluster clus) { + double energyAssumingElectron = m_photonCalib.getEnergy(clus); + double trackMomentum = (new BasicHep3Vector(tr.getMomentum())).magnitude(); + double residual = trackMomentum - energyAssumingElectron; + double estimatedError = 0.2 * Math.sqrt(trackMomentum); + if (trackMomentum < 1.0) { + // Don't shrink the error too much. + estimatedError = 0.2; + } + return (residual/estimatedError); + } + + + private int countHitsInCoreInFirstLayers(Track tr, Cluster clus, int nLayers) { + // Until we come up with a way to do this with a polyhedral + // detector, bypass the check + if(ci.getNSides(CalorimeterType.EM_BARREL) > 2)return nLayers; + Set<Long> coreClusterHits = new HashSet<Long>(); + for (CalorimeterHit hit : clus.getClusters().get(0).getCalorimeterHits()) { + coreClusterHits.add(hit.getCellID()); + } + int countMatches = 0; + HelixExtrapolationResult result = m_findCluster.performExtrapolation(tr); + if (result != null) { + for (int iLayer=0; iLayer<nLayers; iLayer++) { + Long cellID = result.extendToECALLayerAndFindCell(iLayer); + if (cellID != null && coreClusterHits.contains(cellID)) { + countMatches++; + } + } + } + return countMatches; + } + + + private double distanceFromTrackToPhotonCore(Track tr, Cluster clus) { + HelixExtrapolationResult result = m_findCluster.performExtrapolation(tr); + Hep3Vector interceptPoint = null; + if (result != null) { + interceptPoint = result.getInterceptPoint(); + } + if (interceptPoint != null) { + Cluster coreSubCluster = clus.getClusters().get(0); + BasicCluster copyOfCoreSubCluster = new BasicCluster(); + copyOfCoreSubCluster.addCluster(coreSubCluster); + TensorClusterPropertyCalculator calc = new TensorClusterPropertyCalculator(); + copyOfCoreSubCluster.setPropertyCalculator(calc); + copyOfCoreSubCluster.calculateProperties(); + double[][]axes = calc.getPrincipleAxis(); + Hep3Vector coreDirection = new BasicHep3Vector(axes[0][0], axes[0][1], axes[0][2]); + Hep3Vector corePosition = new BasicHep3Vector(calc.getPosition()); + Line line = new Line(corePosition, coreDirection); + double s = line.getDistanceToPoint(interceptPoint); + Hep3Vector poca = line.getPointAtDistance(s); + double doca = VecOp.sub(poca, interceptPoint).magnitude(); + return doca; + } else { + return Double.NaN; + } + } + +}
diff -N TrackToGenericClusterMapMaker.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ TrackToGenericClusterMapMaker.java 11 Apr 2012 15:49:35 -0000 1.1 @@ -0,0 +1,112 @@
+package org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier; + +import java.util.*; +import org.lcsim.util.*; +import org.lcsim.event.*; +import org.lcsim.event.util.*; +import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.*; + +public class TrackToGenericClusterMapMaker extends TrackToClusterMapMaker { + + protected HelixExtrapolator m_findCluster; + public TrackToGenericClusterMapMaker(HelixExtrapolator findCluster, String inputTrackList, String outputMap, String outputUnmatchedTrackList) { + super(inputTrackList, outputMap, outputUnmatchedTrackList); + m_findCluster = findCluster; + } + + protected Map<String,String> m_mapInputNameToMatchedOutputName = new HashMap<String,String>(); + protected Map<String,String> m_mapInputNameToUnmatchedOutputName = new HashMap<String,String>(); + public void addInputList(String inputName, String matchedOutputName, String unmatchedOutputName) { + m_mapInputNameToMatchedOutputName.put(inputName, matchedOutputName); + m_mapInputNameToUnmatchedOutputName.put(inputName, unmatchedOutputName); + } + + protected Map<Track,Cluster> makeMap(EventHeader event) { + // Read in inputs + List<Track> trackList = event.get(Track.class, m_inputTrackListName); + Map<String, List<Cluster>> inputLists = new HashMap<String, List<Cluster>>(); + for (String str : m_mapInputNameToMatchedOutputName.keySet()) { + List<Cluster> currentList = event.get(Cluster.class, str); + inputLists.put(str, currentList); + } + if (inputLists.size() != m_mapInputNameToMatchedOutputName.size()) { throw new AssertionError("Book-keeping error"); } + if (inputLists.size() != m_mapInputNameToUnmatchedOutputName.size()) { throw new AssertionError("Book-keeping error"); } + + // Set up matching + LocalHelixExtrapolationTrackMIPClusterMatcher mipMatch = new LocalHelixExtrapolationTrackMIPClusterMatcher(m_findCluster); + LocalHelixExtrapolationTrackClusterMatcher genMatch = new LocalHelixExtrapolationTrackClusterMatcher(m_findCluster); + DualActionTrackClusterMatcher dualMatch = new DualActionTrackClusterMatcher(mipMatch, genMatch); + mipMatch.process(event); + genMatch.process(event); + List<Cluster> allMatchableClusters = new Vector<Cluster>(); + for (List<Cluster> inputList : inputLists.values()) { + allMatchableClusters.addAll(inputList); + } + + // Do matching + Map<Track,Cluster> tracksMatchedToClusters = new HashMap<Track,Cluster>(); + Map<Cluster, List<Track>> clustersMatchedToTracks = new HashMap<Cluster, List<Track>>(); + for (Track tr : trackList) { + Cluster matchedCluster = dualMatch.matchTrackToCluster(tr, allMatchableClusters); + if (matchedCluster != null) { + // Found a match + // Optionally, handle these cases: + // * Match is to a teeny cluster piece (leftoverHitClusters) but there is structure nearby inside same DTree + // * Match is to a photon (try to split up) + // * Match is to a cluster with E>>p (try to split up) + // ... but those don't really apply here (they aren't MIPs) + tracksMatchedToClusters.put(tr, matchedCluster); + List<Track> clusTrList = clustersMatchedToTracks.get(matchedCluster); + if (clusTrList == null) { + clusTrList = new Vector<Track>(); + clustersMatchedToTracks.put(matchedCluster, clusTrList); + } + clusTrList.add(tr); + } + } + + // Flag unique matches to be written out: + Map<Track,Cluster> outputMap = new HashMap<Track,Cluster>(); + for (Track tr : tracksMatchedToClusters.keySet()) { + Cluster matchedClus = tracksMatchedToClusters.get(tr); + List<Track> tracksOfMatchedClus = clustersMatchedToTracks.get(matchedClus); + if (tracksOfMatchedClus == null) { throw new AssertionError("Book-keeping error!"); } + if (tracksOfMatchedClus.size()==0) { + throw new AssertionError("Book-keeping error!"); + } else if (tracksOfMatchedClus.size()==1) { + // Unique match -- OK + outputMap.put(tr, matchedClus); + } else { + // Ambiguous match -- ignore for now + } + } + + // Identify unmatched tracks + List<Track> unmatchedTracks = new Vector<Track>(); + unmatchedTracks.addAll(trackList); + unmatchedTracks.removeAll(outputMap.keySet()); + + // Separate out lists of matched & unmatched clusters + for (String str : m_mapInputNameToMatchedOutputName.keySet()) { + List<Cluster> inputList = inputLists.get(str); + List<Cluster> outputListMatched = new Vector<Cluster>(); + List<Cluster> outputListUnmatched = new Vector<Cluster>(); + String matchedOutputName = m_mapInputNameToMatchedOutputName.get(str); + String unmatchedOutputName = m_mapInputNameToUnmatchedOutputName.get(str); + for (Cluster clus : inputList) { + if (outputMap.values().contains(clus)) { + outputListMatched.add(clus); + } else { + outputListUnmatched.add(clus); + } + } + event.put(matchedOutputName, outputListMatched); + event.put(unmatchedOutputName, outputListUnmatched); + } + + // All done + event.put(m_outputUnmatchedTrackListName, unmatchedTracks); + return outputMap; + } +} +
diff -N TrackToMipClusterMapMaker.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ TrackToMipClusterMapMaker.java 11 Apr 2012 15:49:35 -0000 1.1 @@ -0,0 +1,102 @@
+package org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier; + +import java.util.*; +import org.lcsim.util.*; +import org.lcsim.event.*; +import org.lcsim.event.util.*; +import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.*; + +public class TrackToMipClusterMapMaker extends TrackToClusterMapMaker { + protected HelixExtrapolator m_findCluster; + public TrackToMipClusterMapMaker(HelixExtrapolator findCluster, String inputTrackList, String outputMap, String outputUnmatchedTrackList) { + super(inputTrackList, outputMap, outputUnmatchedTrackList); + m_findCluster = findCluster; + } + + protected Map<String,String> m_mapInputNameToMatchedOutputName = new HashMap<String,String>(); + protected Map<String,String> m_mapInputNameToUnmatchedOutputName = new HashMap<String,String>(); + public void addInputList(String inputName, String matchedOutputName, String unmatchedOutputName) { + m_mapInputNameToMatchedOutputName.put(inputName, matchedOutputName); + m_mapInputNameToUnmatchedOutputName.put(inputName, unmatchedOutputName); + } + + protected Map<Track,Cluster> makeMap(EventHeader event) { + // Read in inputs + List<Track> trackList = event.get(Track.class, m_inputTrackListName); + Map<String, List<Cluster>> inputLists = new HashMap<String, List<Cluster>>(); + for (String str : m_mapInputNameToMatchedOutputName.keySet()) { + List<Cluster> currentList = event.get(Cluster.class, str); + inputLists.put(str, currentList); + } + if (inputLists.size() != m_mapInputNameToMatchedOutputName.size()) { throw new AssertionError("Book-keeping error"); } + if (inputLists.size() != m_mapInputNameToUnmatchedOutputName.size()) { throw new AssertionError("Book-keeping error"); } + + // Set up matching + LocalHelixExtrapolationTrackMIPClusterMatcher mipMatch = new LocalHelixExtrapolationTrackMIPClusterMatcher(m_findCluster); + mipMatch.process(event); + List<Cluster> allMatchableClusters = new Vector<Cluster>(); + for (List<Cluster> inputList : inputLists.values()) { + allMatchableClusters.addAll(inputList); + } + + // Do matching + Map<Track,Cluster> tracksMatchedToClusters = new HashMap<Track,Cluster>(); + Map<Cluster, List<Track>> clustersMatchedToTracks = new HashMap<Cluster, List<Track>>(); + for (Track tr : trackList) { + Cluster matchedCluster = mipMatch.matchTrackToCluster(tr, allMatchableClusters); + if (matchedCluster != null) { + // Found a match + tracksMatchedToClusters.put(tr, matchedCluster); + List<Track> clusTrList = clustersMatchedToTracks.get(matchedCluster); + if (clusTrList == null) { + clusTrList = new Vector<Track>(); + clustersMatchedToTracks.put(matchedCluster, clusTrList); + } + clusTrList.add(tr); + } + } + + // Flag unique matches to be written out: + Map<Track,Cluster> outputMap = new HashMap<Track,Cluster>(); + for (Track tr : tracksMatchedToClusters.keySet()) { + Cluster matchedClus = tracksMatchedToClusters.get(tr); + List<Track> tracksOfMatchedClus = clustersMatchedToTracks.get(matchedClus); + if (tracksOfMatchedClus == null) { throw new AssertionError("Book-keeping error!"); } + if (tracksOfMatchedClus.size()==0) { + throw new AssertionError("Book-keeping error!"); + } else if (tracksOfMatchedClus.size()==1) { + // Unique match -- OK + outputMap.put(tr, matchedClus); + } else { + // Ambiguous match -- ignore for now + } + } + + // Identify unmatched tracks + List<Track> unmatchedTracks = new Vector<Track>(); + unmatchedTracks.addAll(trackList); + unmatchedTracks.removeAll(outputMap.keySet()); + + // Separate out lists of matched & unmatched clusters + for (String str : m_mapInputNameToMatchedOutputName.keySet()) { + List<Cluster> inputList = inputLists.get(str); + List<Cluster> outputListMatched = new Vector<Cluster>(); + List<Cluster> outputListUnmatched = new Vector<Cluster>(); + String matchedOutputName = m_mapInputNameToMatchedOutputName.get(str); + String unmatchedOutputName = m_mapInputNameToUnmatchedOutputName.get(str); + for (Cluster clus : inputList) { + if (outputMap.values().contains(clus)) { + outputListMatched.add(clus); + } else { + outputListUnmatched.add(clus); + } + } + event.put(matchedOutputName, outputListMatched); + event.put(unmatchedOutputName, outputListUnmatched); + } + + // All done + event.put(m_outputUnmatchedTrackListName, unmatchedTracks); + return outputMap; + } +}
diff -N TrackToPreShowerMipMapMaker.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ TrackToPreShowerMipMapMaker.java 11 Apr 2012 15:49:35 -0000 1.1 @@ -0,0 +1,159 @@
+package org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier; + +import java.util.*; +import org.lcsim.util.*; +import org.lcsim.event.*; +import org.lcsim.event.util.*; +import org.lcsim.recon.cluster.util.BasicCluster; + +public class TrackToPreShowerMipMapMaker extends TrackToClusterMapMaker { + + String m_inputMapTrkToMIP; + String m_outputMips; + String m_outputSmallClusters; + String m_outputBlocks; + public TrackToPreShowerMipMapMaker(String inputMapTrkToMIP, String inputTrackList, String outputMap, String outputUnmatchedTrackList, String outputMips, String outputSmallClusters, String outputBlocks) { + super(inputTrackList, outputMap, outputUnmatchedTrackList); + m_inputMapTrkToMIP = inputMapTrkToMIP; + m_outputMips = outputMips; + m_outputSmallClusters = outputSmallClusters; + m_outputBlocks = outputBlocks; + } + + protected Map<Track,Cluster> makeMap(EventHeader event) { + // The output + Map<Track,Cluster> outputMap = new HashMap<Track,Cluster>(); + List<Cluster> outputClustersMips = new Vector<Cluster>(); + List<Cluster> outputClustersBlocks = new Vector<Cluster>(); + List<Cluster> outputClustersSmall = new Vector<Cluster>(); + + // Read in MIP connections + List<Track> inputTrackList = event.get(Track.class, m_inputTrackListName); + Map<Track,BasicCluster> MapTrkToMIP = (Map<Track,BasicCluster>)(event.get(m_inputMapTrkToMIP)); + + // Now, each track is connected to a MIP. But some of these MIP clusters + // may overlap. We need to identify the cases when that happens and then + // * produce a merged cluster + // * have each of the tracks pointing to the same merged cluster + // First, check for overlaps... + Map<Cluster,Track> mapMipToTrack = new HashMap<Cluster,Track>(); + Map<Cluster,Cluster> mapMipToMergedCluster = new HashMap<Cluster,Cluster>(); + Map<Cluster,List<Track>> mapMergedClusterToTracks = new HashMap<Cluster,List<Track>>(); + + // Find hits for each MIP & which clusters they're inside + Map<CalorimeterHit,Set<Cluster>> hitMipMap = new HashMap<CalorimeterHit,Set<Cluster>>(); + for (Track tr : MapTrkToMIP.keySet()) { + if (!inputTrackList.contains(tr)) { throw new AssertionError("Book-keeping error"); } + BasicCluster mip = MapTrkToMIP.get(tr); + mapMipToTrack.put(mip,tr); + for (CalorimeterHit hit : mip.getCalorimeterHits()) { + Set<Cluster> mipsOfHit = hitMipMap.get(hit); + if (mipsOfHit == null) { + mipsOfHit= new HashSet<Cluster>(); + hitMipMap.put(hit, mipsOfHit); + } + mipsOfHit.add(mip); + } + } + + // Look for groups of mips such that + // * Every MIP in a group is connected (directly or indirectly) + // to every other MIP in the group. + // * Every MIP appears in exactly one group. + List<Set<Cluster>> mipOverlapSets = new Vector<Set<Cluster>>(); + for (CalorimeterHit hit : hitMipMap.keySet()) { + Set<Cluster> touchedClusters = hitMipMap.get(hit); + Set<Set<Cluster>> oldLinkedClusterSets = new HashSet<Set<Cluster>>(); + for (Cluster clus : touchedClusters) { + for (Set<Cluster> currentSet : mipOverlapSets) { + if (currentSet.contains(clus)) { + oldLinkedClusterSets.add(currentSet); + } + } + } + Set<Cluster> newLinkedClusterSet = new HashSet<Cluster>(); + newLinkedClusterSet.addAll(touchedClusters); + for (Set<Cluster> oldSet : oldLinkedClusterSets) { + newLinkedClusterSet.addAll(oldSet); + mipOverlapSets.remove(oldSet); + } + mipOverlapSets.add(newLinkedClusterSet); + } + + // Verify that each cluster appears in exactly one set + List<Cluster> countedClusterList = new Vector<Cluster>(); + Set<Cluster> countedClusterSet = new HashSet<Cluster>(); + for (Set<Cluster> currentSet : mipOverlapSets) { + countedClusterList.addAll(currentSet); + countedClusterSet.addAll(currentSet); + } + if (countedClusterList.size() != MapTrkToMIP.size()) { throw new AssertionError("Book-keeping error"); } + if (countedClusterSet.size() != MapTrkToMIP.size()) { throw new AssertionError("Book-keeping error"); } + + // Do the merge of overlapping MIPs + for (Set<Cluster> currentSet : mipOverlapSets) { + if (currentSet.size()==0) { + throw new AssertionError("Empty set!"); + } else if (currentSet.size()==1) { + Cluster mip = currentSet.iterator().next(); + mapMipToMergedCluster.put(mip,mip); + Track tr = mapMipToTrack.get(mip); + List<Track> mergedTracks = new Vector<Track>(); + mergedTracks.add(tr); + mapMergedClusterToTracks.put(mip, mergedTracks); + } else { + BasicCluster mergedMip = new BasicCluster(); + List<Track> mergedTracks = new Vector<Track>(); + Set<CalorimeterHit> mergedHits = new HashSet<CalorimeterHit>(); + for (Cluster mip : currentSet) { + mergedHits.addAll(mip.getCalorimeterHits()); + Track tr = mapMipToTrack.get(mip); + mergedTracks.add(tr); + } + for (CalorimeterHit hit : mergedHits) { + mergedMip.addHit(hit); + } + for (Cluster clus : currentSet) { + mapMipToMergedCluster.put(clus, mergedMip); + mapMergedClusterToTracks.put(mergedMip, mergedTracks); + } + } + } + + // Assign MIPs to tracks, taking overlaps into account + for (Cluster mergedMip : mapMergedClusterToTracks.keySet()) { + List<Track> tracks = mapMergedClusterToTracks.get(mergedMip); + if (tracks == null) { throw new AssertionError("Null tracks!"); } + if (tracks.size()==0) { + throw new AssertionError("Empty track list!"); + } else if (tracks.size()==1) { + // Unique + Track tr = tracks.get(0); + if (mergedMip.getCalorimeterHits().size() > 5) { + // Found a good MIP + outputMap.put(tr, mergedMip); + outputClustersMips.add(mergedMip); + } else { + // Didn't find a good mip + outputClustersSmall.add(mergedMip); + } + } else { + // Overlap -- can't treat it as a MIP. + outputClustersBlocks.add(mergedMip); + } + } + + // Identify unmatched tracks + List<Track> unmatchedTracks = new Vector<Track>(); + unmatchedTracks.addAll(inputTrackList); + unmatchedTracks.removeAll(outputMap.keySet()); + + // All done + int flag = 1<<org.lcsim.util.lcio.LCIOConstants.CLBIT_HITS; + event.put(m_outputMips, outputClustersMips, Cluster.class, flag); + event.put(m_outputBlocks, outputClustersBlocks, Cluster.class, flag); + event.put(m_outputSmallClusters, outputClustersSmall, Cluster.class, flag); + event.put(m_outputUnmatchedTrackListName, unmatchedTracks); + return outputMap; + } +}
diff -N PFADetectorLayer.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ PFADetectorLayer.java 11 Apr 2012 15:49:36 -0000 1.1 @@ -0,0 +1,376 @@
+ +package org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.structural; + +import java.util.*; +import hep.physics.vec.*; +import org.lcsim.util.*; +import org.lcsim.event.*; +import org.lcsim.recon.util.CalorimeterInformation; +import org.lcsim.geometry.Calorimeter.CalorimeterType; +import org.lcsim.geometry.*; + +public class PFADetectorLayer +{ + protected int m_id; + protected int m_layerNumber; + protected CalorimeterType m_type; + + /** + * Default constructor: instantiate an invalid layer + */ + public PFADetectorLayer() + { + m_id = -1; + m_type = CalorimeterType.UNKNOWN; + } + + public PFADetectorLayer( int id , int layerNumber ) + { + m_id = id; + m_layerNumber = layerNumber; + + CalorimeterInformation ci = CalorimeterInformation.instance(); + double n1 = ci.getNLayers( CalorimeterType.EM_BARREL ); + double n2 = ci.getNLayers( CalorimeterType.HAD_BARREL ); + double n3 = ci.getNLayers( CalorimeterType.MUON_BARREL ); + double n4 = ci.getNLayers( CalorimeterType.EM_ENDCAP ); + double n5 = ci.getNLayers( CalorimeterType.HAD_ENDCAP ); + double n6 = ci.getNLayers( CalorimeterType.MUON_ENDCAP ); + if ( id < n1) m_type = CalorimeterType.EM_BARREL; + else if( id < n1+n2 ) m_type = CalorimeterType.HAD_BARREL; + else if( id < n1+n2+n3 ) m_type = CalorimeterType.MUON_BARREL; + else if( id < n1+n2+n3+n4 ) m_type = CalorimeterType.EM_ENDCAP; + else if( id < n1+n2+n3+n4+n5 ) m_type = CalorimeterType.HAD_ENDCAP; + else if( id < n1+n2+n3+n4+n5+n6 ) m_type = CalorimeterType.MUON_ENDCAP; + else throw new AssertionError(); + } + + /** + * Constructor taking a CalorimeterHit + */ + public PFADetectorLayer( CalorimeterHit hit ) + { + IDDecoder idDecoder = hit.getIDDecoder(); + idDecoder.setID( hit.getCellID() ); + int layer = idDecoder.getLayer(); + + String calorimeterName = hit.getSubdetector().getName(); + CalorimeterInformation ci = CalorimeterInformation.instance(); + + // calculate the layer identifier: + // should preserve the order: inside-out, barrel-endcap + if( calorimeterName.equals( ci.getName( CalorimeterType.EM_BARREL ) ) ) { m_type = CalorimeterType.EM_BARREL; m_id = layer + getSubDetectorOffset( m_type ); m_layerNumber = layer; } + else if( calorimeterName.equals( ci.getName( CalorimeterType.HAD_BARREL ) ) ) { m_type = CalorimeterType.HAD_BARREL; m_id = layer + getSubDetectorOffset( m_type ); m_layerNumber = layer; } + else if( calorimeterName.equals( ci.getName( CalorimeterType.MUON_BARREL ) ) ) { m_type = CalorimeterType.MUON_BARREL; m_id = layer + getSubDetectorOffset( m_type ); m_layerNumber = layer; } + else if( calorimeterName.equals( ci.getName( CalorimeterType.EM_ENDCAP ) ) ) { m_type = CalorimeterType.EM_ENDCAP; m_id = layer + getSubDetectorOffset( m_type ); m_layerNumber = layer; } + else if( calorimeterName.equals( ci.getName( CalorimeterType.HAD_ENDCAP ) ) ) { m_type = CalorimeterType.HAD_ENDCAP; m_id = layer + getSubDetectorOffset( m_type ); m_layerNumber = layer; } + else if( calorimeterName.equals( ci.getName( CalorimeterType.MUON_ENDCAP ) ) ) { m_type = CalorimeterType.MUON_ENDCAP; m_id = layer + getSubDetectorOffset( m_type ); m_layerNumber = layer; } + else throw new AssertionError(); + } + + + public int getSubDetectorOffset( CalorimeterType type ) + { + CalorimeterInformation ci = CalorimeterInformation.instance(); + + if( type == CalorimeterType.EM_BARREL ) return 0; + else if( type == CalorimeterType.HAD_BARREL ) return ci.getNLayers( CalorimeterType.EM_BARREL ); + else if( type == CalorimeterType.MUON_BARREL ) return getSubDetectorOffset( CalorimeterType.HAD_BARREL ) + ci.getNLayers( CalorimeterType.HAD_BARREL ); + else if( type == CalorimeterType.EM_ENDCAP ) return getSubDetectorOffset( CalorimeterType.MUON_BARREL ) + ci.getNLayers( CalorimeterType.MUON_BARREL ); + else if( type == CalorimeterType.HAD_ENDCAP ) return getSubDetectorOffset( CalorimeterType.EM_ENDCAP ) + ci.getNLayers( CalorimeterType.EM_ENDCAP ); + else if( type == CalorimeterType.MUON_ENDCAP ) return getSubDetectorOffset( CalorimeterType.HAD_ENDCAP ) + ci.getNLayers( CalorimeterType.HAD_ENDCAP ); + else throw new AssertionError(); + } + + public int getLayerNumber() + { + return m_layerNumber; + } + + /** + * returns the identifier of the layer + */ + public int id() + { + return m_id; + } + + + /** + * returns the calorimeter type + */ + public CalorimeterType calorimeterType() + { + return m_type; + } + + + /** + * returns the sub-detector name + */ + public String subdetectorName() + { + CalorimeterInformation ci = CalorimeterInformation.instance(); + return ci.getName(m_type); + } + + + /** + * Override the hashCode method to force the identifier to be used as key in maps. + */ + public int hashCode() + { + return id(); + } + + + /** + * Override the equals method to use identifiers to compare two layers. + */ + public boolean equals( Object obj ) + { + if( !(obj instanceof PFADetectorLayer) ) return false; + PFADetectorLayer layer = (PFADetectorLayer)obj; + return id() == layer.id(); + } + + + /** + * Checks validity of the layer as representing a physical layer + */ + public boolean isValid() + { + // checks for valid identifier and sub-detector type + return ( m_id >= 0 && m_type != CalorimeterType.UNKNOWN ); + } + + + /** + * Returns the number of skipped layers from a given layer + * returned value should be 0 if layers are the same + * output should be negative if layers are not passed in the normal order (see LayerSort) + */ + public int getSkipped( PFADetectorLayer layer ) + { + CalorimeterInformation ci = CalorimeterInformation.instance(); + if( isBarrel() && layer.isEndcap() ) return -10000; + if( isEndcap() && layer.isBarrel() ) return -10000; + int first, second; + first = 10000; + second = 10000; + if( isBarrel() ) + { + if( m_type == CalorimeterType.EM_BARREL ) first = getLayerNumber(); + else if( m_type == CalorimeterType.HAD_BARREL ) first = ci.getNLayers( CalorimeterType.EM_BARREL ) + getLayerNumber(); + else if( m_type == CalorimeterType.MUON_BARREL ) first = ci.getNLayers( CalorimeterType.EM_BARREL ) + ci.getNLayers( CalorimeterType.HAD_BARREL ) + getLayerNumber(); + + if( layer.calorimeterType() == CalorimeterType.EM_BARREL ) second = layer.getLayerNumber(); + else if( layer.calorimeterType() == CalorimeterType.HAD_BARREL ) second = ci.getNLayers( CalorimeterType.EM_BARREL ) + layer.getLayerNumber(); + else if( layer.calorimeterType() == CalorimeterType.MUON_BARREL ) second = ci.getNLayers( CalorimeterType.EM_BARREL ) + ci.getNLayers( CalorimeterType.HAD_BARREL ) + layer.getLayerNumber(); + } + else + { + if( m_type == CalorimeterType.EM_ENDCAP ) first = getLayerNumber(); + else if( m_type == CalorimeterType.HAD_ENDCAP ) first = ci.getNLayers( CalorimeterType.EM_ENDCAP ) + getLayerNumber(); + else if( m_type == CalorimeterType.MUON_ENDCAP ) first = ci.getNLayers( CalorimeterType.EM_ENDCAP ) + ci.getNLayers( CalorimeterType.HAD_ENDCAP ) + getLayerNumber(); + + if( layer.calorimeterType() == CalorimeterType.EM_ENDCAP ) second = layer.getLayerNumber(); + else if( layer.calorimeterType() == CalorimeterType.HAD_ENDCAP ) second = ci.getNLayers( CalorimeterType.EM_ENDCAP ) + layer.getLayerNumber(); + else if( layer.calorimeterType() == CalorimeterType.MUON_ENDCAP ) second = ci.getNLayers( CalorimeterType.EM_ENDCAP ) + ci.getNLayers( CalorimeterType.HAD_ENDCAP ) + layer.getLayerNumber(); + } + return ( first - second ); + } + + public double getCellSize() // to fixe + { + if( m_type == CalorimeterType.EM_BARREL ) return 3.5; + else if( m_type == CalorimeterType.HAD_BARREL ) return 10.; + else if( m_type == CalorimeterType.MUON_BARREL ) return 1000000.; // to fixe + else if( m_type == CalorimeterType.EM_ENDCAP ) return 3.5; + else if( m_type == CalorimeterType.HAD_ENDCAP ) return 10.; + else if( m_type == CalorimeterType.MUON_ENDCAP ) return 1000000.; // to fixe + else return 1000000.; + } + + public double getDistanceToIP() + { + CalorimeterInformation ci = CalorimeterInformation.instance(); + if( m_type == CalorimeterType.EM_BARREL ) + { + if ( getLayerNumber() <= 20 ) return ci.getRMin( CalorimeterType.EM_BARREL ) + ( getLayerNumber() * 3.5 ) + 0.16; + else if( getLayerNumber() <= 30 ) return ci.getRMin( CalorimeterType.EM_BARREL ) + ( 3.5 * 20. ) + ( (getLayerNumber() - 20) * 6. ) + 0.16; + else throw new AssertionError(); + } + else if( m_type == CalorimeterType.HAD_BARREL ) return ci.getRMin( CalorimeterType.HAD_BARREL ) + ( getLayerNumber() * 28. ) + 21.7; + else if( m_type == CalorimeterType.MUON_BARREL ) return ci.getRMin( CalorimeterType.MUON_BARREL ) + getLayerNumber() * ( ci.getRMax( CalorimeterType.MUON_BARREL ) - ci.getRMin( CalorimeterType.MUON_BARREL ) ) / ci.getNLayers( CalorimeterType.MUON_BARREL ); + else if( m_type == CalorimeterType.EM_ENDCAP ) + { + if ( getLayerNumber() <= 20 ) return ci.getZMin( CalorimeterType.EM_ENDCAP ) + ( getLayerNumber() * 3.5 ) + 0.16; + else if( getLayerNumber() <= 30 ) return ci.getZMin( CalorimeterType.EM_ENDCAP ) + ( 3.5 * 20. ) + ( ( getLayerNumber() - 20 ) * 6. ) + 0.16; + else throw new AssertionError(); + } + else if( m_type == CalorimeterType.HAD_ENDCAP ) return ci.getZMin( CalorimeterType.HAD_ENDCAP ) + ( getLayerNumber() * 28. ) + 21.7; + else if( m_type == CalorimeterType.MUON_ENDCAP ) return ci.getZMin( CalorimeterType.MUON_ENDCAP ) + getLayerNumber() * ( ci.getZMax( CalorimeterType.MUON_ENDCAP ) - ci.getZMin( CalorimeterType.MUON_ENDCAP ) ) / ci.getNLayers( CalorimeterType.MUON_ENDCAP ); + else throw new AssertionError(); + //if( m_id < 20 ) return 3.5; + //else if( 20 <= baseLayer && baseLayer < 30 ) return 6.; + //else if( baseLayer == 30 ) return 31.54; + //else return 28.; + } + + public double getDistanceToLayer( PFADetectorLayer layer ) // to fixe + { + if( isBarrel() && layer.isEndcap() ) return -1000000.; + if( isEndcap() && layer.isBarrel() ) return -1000000.; + double d = getDistanceToIP() - layer.getDistanceToIP(); + if( d < 0. ) d *= -1.; + return d; + } + + public double getDistanceToNextLayer() + { + PFADetectorLayer nextLayer = getNextLayer(); + if( nextLayer == null ) throw new AssertionError(); + return nextLayer.getDistanceToIP() - getDistanceToIP(); + } + + public PFADetectorLayer getNextLayer() + { + CalorimeterInformation ci = CalorimeterInformation.instance(); + if( isBarrel() && id() == ci.getNLayers( CalorimeterType.EM_BARREL ) + ci.getNLayers( CalorimeterType.HAD_BARREL ) + ci.getNLayers( CalorimeterType.MUON_BARREL ) - 1 ) return null; + if( isEndcap() && id() == ci.getNLayers( CalorimeterType.EM_ENDCAP ) + ci.getNLayers( CalorimeterType.HAD_ENDCAP ) + ci.getNLayers( CalorimeterType.MUON_ENDCAP ) - 1 ) return null; + return new PFADetectorLayer( id() + 1 , 0); + } + + public double getDistanceBetweenLayers( PFADetectorLayer layer1 , PFADetectorLayer layer2 ) + { + if( layer1.isBarrel() && !layer2.isBarrel() ) throw new AssertionError(); + if( layer1.isEndcap() && !layer2.isEndcap() ) throw new AssertionError(); + double d = layer1.getDistanceToIP() - layer2.getDistanceToIP(); + if( d < 0 ) d *= -1.; + return d; + } + + /** + * Returns true if the layer is in the barrel + */ + public boolean isBarrel() + { + if( m_type == CalorimeterType.EM_BARREL ) return true; + if( m_type == CalorimeterType.HAD_BARREL ) return true; + if( m_type == CalorimeterType.MUON_BARREL ) return true; + return false; + } + + + /** + * Returns true if the layer is in the endcap + */ + public boolean isEndcap() + { + if( m_type == CalorimeterType.EM_ENDCAP ) return true; + if( m_type == CalorimeterType.HAD_ENDCAP ) return true; + if( m_type == CalorimeterType.MUON_ENDCAP ) return true; + return false; + } + + + public Hep3Vector getInterceptPoint( Hep3Vector P , Hep3Vector v ) + { + CalorimeterInformation ci = CalorimeterInformation.instance(); + if( isEndcap() ) + { + + double signOfZ = P.z() < 0. ? -1. : +1.; + Hep3Vector n = new BasicHep3Vector( 0 , 0 , 1 ); // vecteur de plan + Hep3Vector A = new BasicHep3Vector( 0 , 0 , signOfZ * getDistanceToIP() ); // point sur le plan + + double x,y,z; + x = (A.x()*n.x()) - (P.y()*n.y()) - (P.z()*n.z()) + ( ( (v.y()*n.y()) + (v.z()*n.z()) ) * (P.x()/v.x()) ) + (A.y()*n.y()) + (A.z()*n.z()); + x /= ( n.x() + ( ( (v.y()*n.y()) + (v.z()*n.z()) ) / v.x() ) ); + y = (A.y()*n.y()) - (P.x()*n.x()) - (P.z()*n.z()) + ( ( (v.x()*n.x()) + (v.z()*n.z()) ) * (P.y()/v.y()) ) + (A.x()*n.x()) + (A.z()*n.z()); + y /= ( n.y() + ( ( (v.x()*n.x()) + (v.z()*n.z()) ) / v.y() ) ); + z = (A.z()*n.z()) - (P.x()*n.x()) - (P.y()*n.y()) + ( ( (v.x()*n.x()) + (v.y()*n.y()) ) * (P.z()/v.z()) ) + (A.x()*n.x()) + (A.y()*n.y()); + z /= ( n.z() + ( ( (v.x()*n.x()) + (v.y()*n.y()) ) / v.z() ) ); + + double r = Math.sqrt( x*x + y*y ); + double rmin = ci.getRMin( m_type ); + double rmax = ci.getRMax( m_type ); + if( rmin <= r && r <= rmax ) return new BasicHep3Vector( x , y , z ); + else return null; + } + else if( isBarrel() ) + { + double a,b,c,m,delta; + double x1,x2,y1,y2,z1,z2; + double R = getDistanceToIP(); // radius of the layer + + m = v.y() / v.x(); + a = 1. + m*m; + b = ( 2. * m ) * ( P.y() - (m*P.x()) ); + c = (m*m)*(P.x()*P.x()) - (2.*m*P.x()*P.y()) + (P.y()*P.y())- (R*R); + delta = (b*b) - (4.*a*c); + if( delta > 0. ) { x1 = ( - b - Math.sqrt(delta) ) / (2.*a); x2 = ( - b + Math.sqrt(delta) ) / (2.*a); } + else return null; + + m = v.x() / v.y(); + a = 1. + m*m; + b = ( 2. * m ) * ( P.x() - (m*P.y()) ); + c = (m*m)*(P.y()*P.y()) - (2.*m*P.y()*P.x()) + (P.x()*P.x())- (R*R); + delta = (b*b) - (4.*a*c); + if( delta > 0. ) { y1 = ( - b - Math.sqrt(delta) ) / (2.*a); y2 = ( - b + Math.sqrt(delta) ) / (2.*a); } + else return null; + + double cylinder11 = x1*x1 + y1*y1 - R*R; cylinder11 = cylinder11 * cylinder11; + double cylinder12 = x1*x1 + y2*y2 - R*R; cylinder12 = cylinder12 * cylinder12; + double cylinder21 = x2*x2 + y1*y1 - R*R; cylinder21 = cylinder21 * cylinder21; + double cylinder22 = x2*x2 + y2*y2 - R*R; cylinder22 = cylinder22 * cylinder22; + + z1 = ( v.z() / v.x() ) * ( x1 - P.x() ) + P.z(); + z2 = ( v.z() / v.x() ) * ( x2 - P.x() ) + P.z(); + + Vector<Hep3Vector> sol = new Vector<Hep3Vector>();; + if( cylinder11 < 1.e-6 ) sol.add( new BasicHep3Vector( x1 , y1 , z1 ) ); + if( cylinder12 < 1.e-6 ) sol.add( new BasicHep3Vector( x1 , y2 , z1 ) ); + if( cylinder21 < 1.e-6 ) sol.add( new BasicHep3Vector( x2 , y1 , z2 ) ); + if( cylinder22 < 1.e-6 ) sol.add( new BasicHep3Vector( x2 , y2 , z2 ) ); + if( sol.size() != 2 ) return null; //throw new AssertionError("found "+sol.size()+" solutions among: "+cylinder11+" "+cylinder12+" "+cylinder21+" "+cylinder22); + + Hep3Vector M = null; + if( VecOp.sub( sol.get(0) , P ).magnitude() < VecOp.sub( sol.get(1) , P ).magnitude() ) M = sol.get(0); + else M = sol.get(1); + + double z = M.z(); + double zmin = -1. * ci.getZMax( m_type ); + double zmax = +1. * ci.getZMax( m_type ); + if( zmin <= z && z <= zmax ) return M; + else return null; + } + else throw new AssertionError(); + } + + + + /** + * Comparator ordering layers from inside-out, barrel-endcap + */ + static public class LayerSort implements Comparator<PFADetectorLayer> { + + // constructor + public LayerSort() {} + + // compare the identiers + // the identifiers should be calculated such that to preserve the order: inside-out, barrel-endcap + public int compare(PFADetectorLayer l1, PFADetectorLayer l2) { + if (l1.id() < l2.id()) { + return -1; + } else if (l1.id() > l2.id()) { + return 1; + } else { + return 0; + } + } + } + + +}
diff -N PFAWrapper.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ PFAWrapper.java 11 Apr 2012 15:49:36 -0000 1.1 @@ -0,0 +1,168 @@
+package org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.structural; + +import java.util.*; +import org.lcsim.util.Driver; +import org.lcsim.event.EventHeader; +import org.lcsim.util.loop.LCIODriver; +import org.lcsim.util.*; +import org.lcsim.event.*; +import org.lcsim.contrib.uiowa.uiowapfa.recon.cluster.structural.likelihood.LikelihoodEvaluatorWrapper; +import org.lcsim.recon.pfa.output.*; +import org.lcsim.recon.util.CalInfoDriver; + +/** + * Example driver to create PFA output with a list of + * ReconstructedParticle objects. The output is written + * to "test.slcio". In addition, some dijet mass plots + * are written to "output-write.aida". + * + * Beware that the LCIO output file will be quite large! + * Some attempt is made to slim it down, but if space is + * an issue you may need to cut out more of the output + * (see code in the writeOutMini() subroutine for how this + * is done). + * + * There is no acceptance cut built in, since this depends + * on what kind of event you are looking at. + */ + +public class PFAWrapper extends Driver +{ + + // input track collection + protected String trackInput = "Tracks"; + public void setTrackInput(String tracks) { this.trackInput = tracks; } + + // input MC list + protected String mcInput = "ReconFSParticles"; + public void setMcInput(String mcList) { this.mcInput = mcList; } + + // run mode: [0] analysis - [1] training + protected int runMode = 0; + public void setRunMode(int mode){ this.runMode = mode; } + + // flag to run LOI baseline pfa + protected boolean doBaseline = false; + public void setDoBaseline(boolean baseline) { doBaseline = baseline; } + + // flag to set number of iterations + protected int numberOfShowerBuildingIterations = 3; + public void setNumberOfShowerBuildingIterations(int n) { numberOfShowerBuildingIterations = n; } + + protected SetUpPFA pfa; + protected EventSelection m_eventSelection; + + /** Constructor sets up daughter drivers. */ + public PFAWrapper() + { + // Cash general calorimeter information + add(new CalInfoDriver()); + + // Prepare to run PFA: digitize calorimeter hits + add(new org.lcsim.digisim.DigiPackageDriver()); + + // Set up and run PFA + pfa = new SetUpPFA(); + add(pfa); + + // Output + add(new FlushReconstructedParticlesDriver("DTreeReclusteredParticles", "FlushedDTreeReclusteredParticles", "FlushedDTreeReclusteredClusters")); + + // event selection + m_eventSelection = new EventSelection(0, 0.95); + + writeOutMini("full.slcio"); // Write out to an LCIO file + } + + protected boolean m_init = false; + protected void process(EventHeader event){ + + if(!m_init){ + m_init = true; + + pfa.setTrackList(trackInput); + pfa.setMcList(mcInput); + pfa.setRunMode(runMode); + pfa.doBaseline(doBaseline); + pfa.numberOfIterations(numberOfShowerBuildingIterations); + } + + // if(m_eventSelection.pass(event)){ + super.process(event); + //} + } + + void writeOutMini(String filename) { + // Avoid writing out a lot of things that were not in the original event and + // a) were generated and used by us internally, and will not be needed; or + // b) were generated by someone else. + + Vector<String> v = new Vector<String>(); + // Particles + v.add("CheatReconstructedParticles"); + v.add("TempCheatParticles"); + v.add("GenPerfectReconParticles"); + v.add("GenPerfectReconParticles"); + v.add("ReconPerfectReconParticles"); + v.add("GenPerfectVisReconParticles"); + v.add("ReconPerfectVisReconParticles"); + // Tracks & track hits + v.add("TkrEndcapHitsCheatTrackerHits"); + v.add("VtxEndcapHitsCheatTrackerHits"); + v.add("VtxBarrHitsCheatTrackerHits"); + v.add("TkrForwardHitsCheatTrackerHits"); + v.add("TkrBarrHitsCheatTrackerHits"); + v.add("VtxEndcapHitsCheatTracks"); + v.add("VtxBarrHitsCheatTracks"); + v.add("TkrBarrHitsCheatTracks"); + v.add("TkrForwardHitsCheatTracks"); + v.add("TkrEndcapHitsCheatTracks"); + v.add("TempCheatTracks"); + v.add("PerfectTracks"); + v.add("RefinedCheatTracks"); + // CalorimeterHits + v.add("EcalBarrRawHits"); + v.add("ForwardEcalEndcapRawHits"); + v.add("EcalEndcapRawHits"); + v.add("HcalBarrRawHits"); + v.add("HcalEndcapRawHits"); + v.add("EcalBarrDigiHits"); + v.add("EcalBarrelDigiHits"); + v.add("EcalEndcapDigiHits"); + v.add("HcalBarrDigiHits"); + v.add("HcalBarrelDigiHits"); + v.add("HcalEndcapDigiHits"); + v.add("MuonBarrDigiHits"); + v.add("MuonBarrelDigiHits"); + v.add("MuonEndcapDigiHits"); + // Clusters + v.add("EcalEndcapDigiHitsCheatClusters"); + v.add("EcalBarrDigiHitsCheatClusters"); + v.add("HcalBarrDigiHitsCheatClusters"); + v.add("HcalEndcapDigiHitsCheatClusters"); + v.add("ReDTEcalClusters"); + v.add("HcalEndcapDigiHitsDTreeClusters"); + v.add("HcalBarrDigiHitsDTreeClusters"); + v.add("NonFSReconClusters"); + v.add("ReconClusters"); + v.add("EcalBarrDigiHitsDTreeClusters"); + v.add("EcalEndcapDigiHitsDTreeClusters"); + v.add("RefinedCheatClusters"); + v.add("DTEcalClusters"); + v.add("TMClusters"); + // Maps + v.add("EcalEndcapRaw2sim"); + v.add("HcalBarrRaw2sim"); + v.add("HcalEndcapRaw2sim"); + v.add("EcalBarrRaw2sim"); + v.add("ForwardEcalEndcapRaw2sim"); + v.add("TracksToMCP"); + v.add("CheatTracksToMCP"); + // Misc + v.add("MCParticleEndPointEnergy"); + + add(new org.lcsim.util.loop.LCIODriver(filename, v)); + } +} + +
diff -N SlicedShowerBuilder.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ SlicedShowerBuilder.java 11 Apr 2012 15:49:36 -0000 1.1 @@ -0,0 +1,3754 @@
+ +package org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.structural; + +import java.util.*; +import hep.physics.vec.*; +import hep.physics.particle.properties.*; +import org.lcsim.event.*; +import org.lcsim.event.base.*; +import org.lcsim.recon.cluster.util.*; +import org.lcsim.contrib.uiowa.uiowapfa.recon.cluster.clumpfinder.kmean.*; +import org.lcsim.recon.util.CalorimeterInformation; +import org.lcsim.geometry.Calorimeter.CalorimeterType; +import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.*; +import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.structural.shower.*; +import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.structural.sharing.*; +import org.lcsim.math.probability.Erf; + +public class SlicedShowerBuilder +{ + + protected PropertyContainer m_properties; + protected PFABookKeepingBroker m_bookKeeper; + + protected HelixExtrapolator m_extrapolator = null; + + protected ClusterEnergyCalculator m_chargedCalib; + protected ClusterEnergyCalculator m_neutralCalib; + + protected Map<CalorimeterHit, CalorimeterHitType> m_hitTypesMap; + protected Map<CalorimeterHit, Cluster> m_hitToRigidClusterMap; + + // algorithm parameters + protected double m_minDistanceToMipExtrapolationCut = 2; // in units of cell size... + protected double m_mipToMipProximityCut = 2; // in units of cell size... + protected double m_figureOfMeritCutForSmallClusterAssociations = 0.999; + protected double m_figureOfMeritCutForLargeClusterAssociations = 0.1; + protected int m_maxSkippedLayersForCandidateAssociations = 1; + protected int m_maxSkippedLayersForMipToMipAssociations = 2; + protected int m_minSizeToTreatAsBigCluster = 9; + protected double m_maxNumOfCellToIncludeSingleHit = 3.; + + protected double m_energyMomentumTolerance = 2.; // sigmas + protected double m_maxEnergyOfTinyFragments = 1.75; // GeV + protected double m_maxCosAngleToConnectTinyShowers = 0.; + + protected boolean m_debug = false; + + /** + * Constructor + */ + public SlicedShowerBuilder(PFABookKeepingBroker bookKeeper, + PropertyContainer properties, + ClusterEnergyCalculator chargedCalib, + ClusterEnergyCalculator neutralCalib, + HelixExtrapolator extrapolator) + { + m_properties = properties; + m_bookKeeper = bookKeeper; + m_chargedCalib = chargedCalib; + m_neutralCalib = neutralCalib; + m_extrapolator = extrapolator; + } + + + + /*******************************************/ + /***** M A I N A L G O R I T H M *****/ + /*******************************************/ + + + /** + * build hadron showers + */ + public List<ShowerWithBranches> buildShowers(Collection<CalorimeterHit> inputHits, Collection<CalorimeterHit> hitsToShare){ + + /* --------- */ printDebug("buildShowers() called with "+ /* --------- */ + /* --------- */ inputHits.size()+" hits in input"); /* --------- */ + + + /* --------- */ printDebug("resetting maps"); /* --------- */ + + + // reset maps + m_hitTypesMap = new HashMap<CalorimeterHit, CalorimeterHitType>(); + m_hitToRigidClusterMap = new HashMap<CalorimeterHit, Cluster>(); + + + /* --------- */ printDebug("Creating map between hits and rigid clusters"); /* --------- */ + + + // create a map from the hits belonging to MIPs to their corresponding MIP object + createHitToRigidClusterMap(inputHits); + + + /* --------- */ printDebug("Categorizing hits"); /* --------- */ + + + // categorize hits + categorizeHits(inputHits); + + + /* --------- */ printDebug("Sorting hits into layers"); /* --------- */ + + + // sort the hits into layers + Map<PFADetectorLayer, List<CalorimeterHit>> layerToHitListMap = sortHitsIntoLayers(inputHits); + + + /* --------- */ printDebug("Clustering hits into slices"); /* --------- */ + + + // cluster the hits in the form of 2D cluster splices + Map<PFADetectorLayer, List<Cluster>> clusterSlices = getClusterSlices(layerToHitListMap); + + // check that all hits have been used once and only once + { + List<Cluster> allSlicesList = new Vector<Cluster>(); + for(PFADetectorLayer layer : clusterSlices.keySet()) { + List<Cluster> slicesForLayer = clusterSlices.get(layer); + allSlicesList.addAll(slicesForLayer); + } + checkConsistancyOfHitUsage(inputHits, allSlicesList); + } + + + /* --------- */ printDebug("Create map from cluster slices to layers"); /* --------- */ + + + // for ease of book-keeping, create a map from a cluster to its corresponding layer + Map<Cluster, PFADetectorLayer> clusterSliceToLayerMap = new HashMap<Cluster, PFADetectorLayer>(); + for(PFADetectorLayer layer : clusterSlices.keySet()) { + List<Cluster> clustersForLayer = clusterSlices.get(layer); + for(Cluster clus : clustersForLayer) { + clusterSliceToLayerMap.put(clus, layer); + } + } + + + /* --------- */ printDebug("Sorting layers in inside/out-barrel/endcap order"); /* --------- */ + + + // sort layers from inside out + List<PFADetectorLayer> allOccupiedLayers = new Vector<PFADetectorLayer>(); + allOccupiedLayers.addAll(layerToHitListMap.keySet()); + Collections.sort(allOccupiedLayers, new PFADetectorLayer.LayerSort()); + + // list to store output showers + List<ShowerWithBranches> reconstructedShowers = new Vector<ShowerWithBranches>(); + + + /* --------- */ printDebug("Start loop on "+allOccupiedLayers.size()+" layers"); /* --------- */ + + + // loop on layers and build shower + for(PFADetectorLayer layer : allOccupiedLayers) { + + + /* --------- */ printDebug("Treating layer "+layer.id()); /* --------- */ + + + // get the 2D cluster slices for this layer + List<Cluster> clusterSlicesOnThisLayer = clusterSlices.get(layer); + + + /* --------- */ printDebug("There is "+clusterSlicesOnThisLayer.size()+" clusters on layer"); /* --------- */ + /* --------- */ printDebug("Creating candidate associations"); /* --------- */ + + + // find candidates for associations + Map<Cluster, List<ShowerBranch>> clusterToShowerCandidateMap = new HashMap<Cluster, List<ShowerBranch>>(); + Map<ShowerBranch, List<Cluster>> showerToClusterCandidateMap = new HashMap<ShowerBranch, List<Cluster>>(); + createCandidateAssociations(clusterSlicesOnThisLayer, reconstructedShowers, clusterSliceToLayerMap, clusterToShowerCandidateMap, showerToClusterCandidateMap); + + + /* --------- */ printDebug("Found "+clusterToShowerCandidateMap.keySet().size()+ /* --------- */ + /* --------- */ " clusters assigned to at least one shower"); /* --------- */ + + + /* --------- */ printDebug("Resolving ambiguities"); /* --------- */ + + + // resolve ambiguous associations + // this needs the information from the next layer + List<Cluster> clusterSlicesOnNextLayer = null; + int indexOfNextLayer = allOccupiedLayers.indexOf(layer) + 1; + if(indexOfNextLayer < allOccupiedLayers.size()) { + PFADetectorLayer nextLayer = allOccupiedLayers.get(indexOfNextLayer); + clusterSlicesOnNextLayer = clusterSlices.get(nextLayer); + } + resolveAmbiguities(clusterSlicesOnNextLayer, + clusterToShowerCandidateMap, + showerToClusterCandidateMap); + + + /* --------- */ printDebug("Assigning clusters to showers"); /* --------- */ + + + // perform the actual association + assignClustersToShowers(clusterSlicesOnThisLayer, + clusterSliceToLayerMap, + clusterToShowerCandidateMap, + showerToClusterCandidateMap); + + // create showers for unassigned clusters + List<Cluster> unassignedClusters = new Vector<Cluster>(); + unassignedClusters.addAll(clusterSlicesOnThisLayer); + unassignedClusters.removeAll(clusterToShowerCandidateMap.keySet()); + + + /* --------- */ printDebug("creating clusters for "+unassignedClusters.size()+" unassigned Clsuters"); /* --------- */ + + + reconstructedShowers.addAll(createShowersForClusters(unassignedClusters)); + } + + + /* --------- */ printDebug("Done loop on layers; output contains "+reconstructedShowers.size()+" showers"); /* --------- */ + + + // now assign the shared hits + shareLeftoverHits(reconstructedShowers, hitsToShare); + + + /* --------- */ printDebug("Now apply final adjustments to showers: link secondary neutrals and identify unphysical cases"); /* --------- */ + + + // now apply overrides: + // - link secondary neutrals + // - identify unphisical cases + // applyOverrides(reconstructedShowers); + + + // before returning, check that all hits have been used and that no hit has been used in more than one shower + List<Cluster> allShowerCores = new Vector<Cluster>(); + for(ShowerWithBranches shower : reconstructedShowers) { + allShowerCores.add(shower.getCluster()); + } + checkConsistancyOfHitUsage(inputHits, allShowerCores); + + // output + return reconstructedShowers; + } + + + + + /***************************************************/ + /***** A L G O R I T H M I C P I E C E S *****/ + /***************************************************/ + + + /** + * creates a map from hits belonging to MIPs (seeds) to their corresponding MIP (seed) object + */ + protected void createHitToRigidClusterMap( Collection<CalorimeterHit> inputHits ) + { + Collection<Cluster> mips = m_bookKeeper.getClusterList( "Mips" ); + Collection<Cluster> seeds = m_bookKeeper.getClusterList( "Seeds" ); + + for( CalorimeterHit hit : inputHits ) + { + for( Cluster mip : mips ) + { + if( mip.getCalorimeterHits().contains( hit ) ) + { + m_hitToRigidClusterMap.put( hit , mip ); + break; + } + } + + for( Cluster seed : seeds ) + { + if( seed.getCalorimeterHits().contains( hit ) ) + { + m_hitToRigidClusterMap.put( hit , seed ); + break; + } + } + } + } + + + /** + * categorize hits into hits from MIPs, non-MIPs, seeds and non-seeds + */ + protected void categorizeHits( Collection<CalorimeterHit> inputHits ) + { + Collection<Cluster> mips = m_bookKeeper.getClusterList( "Mips" ); + Collection<Cluster> seeds = m_bookKeeper.getClusterList( "Seeds" ); + + for( CalorimeterHit hit : inputHits ) + { + boolean isMip = false; + for( Cluster mip : mips ) + { + if( mip.getCalorimeterHits().contains( hit ) ) + { + isMip = true; + break; + } + } + + boolean isSeed = false; + for( Cluster seed : seeds ) + { + if( seed.getCalorimeterHits().contains( hit ) ) + { + isSeed = true; + break; + } + } + + if( isMip ) + { + if( isSeed ) m_hitTypesMap.put( hit , CalorimeterHitType.CHT_MIP_SEED ); + else m_hitTypesMap.put( hit , CalorimeterHitType.CHT_MIP_NONSEED ); + } + else + { + if( isSeed ) m_hitTypesMap.put( hit , CalorimeterHitType.CHT_NONMIP_SEED ); + else m_hitTypesMap.put( hit , CalorimeterHitType.CHT_NONMIP_NONSEED ); + } + } + } + + + /** + * This method takes a hit list as input and returns a map of hit lists sorted into layers + */ + Map<PFADetectorLayer, List<CalorimeterHit>> sortHitsIntoLayers(Collection<CalorimeterHit> hits) { + + // creates the output + Map<PFADetectorLayer, List<CalorimeterHit>> layerToHitListMap = new HashMap<PFADetectorLayer, List<CalorimeterHit>>(); + + // loop on input hits + for(CalorimeterHit hit : hits){ + + // get the layer for the current hit + PFADetectorLayer layerOfHit = new PFADetectorLayer(hit); + + // hit position + Hep3Vector hitPos = new BasicHep3Vector(hit.getPosition()); + + + /* --------- */ printDebug("Found hit with "+ /* --------- */ + /* --------- */ "[R = "+Math.sqrt(hitPos.x()*hitPos.x()+hitPos.y()*hitPos.y())+ /* --------- */ + /* --------- */ ", Z = "+hitPos.z()+ /* --------- */ + /* --------- */ "] at layer "+layerOfHit.id()+ /* --------- */ + /* --------- */ "which is on detector "+layerOfHit.subdetectorName()+ /* --------- */ + /* --------- */ " at distance "+layerOfHit.getDistanceToIP()+" from IP"); /* --------- */ + + + // get the hits already found on the same layer + List<CalorimeterHit> hitsOnSameLayer = layerToHitListMap.get(layerOfHit); + // add to the map + if(hitsOnSameLayer == null){ + hitsOnSameLayer = new Vector<CalorimeterHit>(); + layerToHitListMap.put(layerOfHit, hitsOnSameLayer); + } + hitsOnSameLayer.add(hit); + } + + return layerToHitListMap; + } + + + /** + * This methods provide 2D clusters split into layers + */ + protected Map<PFADetectorLayer, List<Cluster>> getClusterSlices(Map<PFADetectorLayer, List<CalorimeterHit>> layerToHitListMap){ + + // output + Map<PFADetectorLayer, List<Cluster>> slices = new HashMap<PFADetectorLayer, List<Cluster>> (); + + // configure the k-mean cluster finder + KMeanClumpFinder clus2DFinder = new KMeanClumpFinder(); + + // input parameters + // seed finding + int SDT333 = 0; + int SDT553 = 0; + int SST = 1; + // cluster finding + int CDT333 = 0; + int CDT553 = 0; + int CST = 1; + // number of iterations + int maxItr = 1; + + KMeanParameters kMeanParameters = new KMeanParameters( SDT333 , SDT553 , SST , CDT333 , CDT553 , CST , maxItr ); + clus2DFinder.setParameters( kMeanParameters ); + + // run k-mean on each layer + for(PFADetectorLayer layer : layerToHitListMap.keySet()){ + + // get the hits on the layer + List<CalorimeterHit> hitsOnLayer = layerToHitListMap.get(layer); + + // filter out mip hits + List<CalorimeterHit> nonMipHitsOnLayer = new Vector<CalorimeterHit>(); + for(CalorimeterHit hitToFilter : hitsOnLayer){ + CalorimeterHitType type = getHitType(hitToFilter); + boolean keep = true; + if(type == CalorimeterHitType.CHT_UNKNOWN) keep = false; + if(type == CalorimeterHitType.CHT_MIP_SEED) keep = false; + if(type == CalorimeterHitType.CHT_MIP_NONSEED) keep = false; + if(type == CalorimeterHitType.CHT_NONMIP_SEED) keep = false; + if(keep) { + nonMipHitsOnLayer.add(hitToFilter); + } + } + + // run k-mean + List<Cluster> listClus2D = clus2DFinder.createClusters( nonMipHitsOnLayer ); + + // deal with single hit clusters + List<Cluster> listSingleHit = new Vector<Cluster>(); + List<Cluster> listMultiHit = new Vector<Cluster>(); + for( Cluster clus2D : listClus2D ) { + if( clus2D.getCalorimeterHits().size() == 1 ) { + listSingleHit.add( clus2D ); + }else{ + listMultiHit.add( clus2D ); + } + } + for( Cluster clus2D1 : listSingleHit ) { + Hep3Vector vPos1 = new BasicHep3Vector( clus2D1.getPosition() ); + double distMin = m_maxNumOfCellToIncludeSingleHit * layer.getCellSize(); + Cluster clus2Dmin = null; + for( Cluster clus2D2 : listMultiHit ) { + for( CalorimeterHit hit : clus2D2.getCalorimeterHits() ) { + Hep3Vector vPos2 = new BasicHep3Vector( hit.getPosition() ); + double mDelta = VecOp.sub( vPos1 , vPos2 ).magnitude(); + if( mDelta < distMin ) { + distMin = mDelta; + clus2Dmin = clus2D2; + } + } + } + if( clus2Dmin != null ) { + for( CalorimeterHit hit : clus2D1.getCalorimeterHits() ) { + ((BasicCluster)clus2Dmin).addHit( hit ); + } + listClus2D.remove( clus2D1 ); + } + } + + // after k-mean: check that every hit has been used once and only once + checkConsistancyOfHitUsage(nonMipHitsOnLayer, listClus2D); + + // add hits from MIPs as small clusters + Map<Cluster, BasicCluster> clusterToSliceMap = new HashMap<Cluster, BasicCluster>(); + for(CalorimeterHit hit : hitsOnLayer){ + if( nonMipHitsOnLayer.contains(hit) ) continue; + Cluster clusterForHit = m_hitToRigidClusterMap.get(hit); + if(clusterForHit == null) throw new AssertionError("inconsistent book-keeping"); + BasicCluster sliceForHit = clusterToSliceMap.get(clusterForHit); + if(sliceForHit == null){ + sliceForHit = new BasicCluster(); + clusterToSliceMap.put(clusterForHit, sliceForHit); + } + sliceForHit.addHit(hit); + } + listClus2D.addAll(clusterToSliceMap.values()); + + // after adding MIPs: check that every hit has been used once and only once + checkConsistancyOfHitUsage(hitsOnLayer, listClus2D); + + // save the result + slices.put(layer, listClus2D); + } + + return slices; + } + + + /** + * create candidates for associations between clusters and showers + */ + protected void createCandidateAssociations(List<Cluster> clusterSlicesOnThisLayer, + List<ShowerWithBranches> reconstructedShowers, + Map<Cluster, PFADetectorLayer> clusterSliceToLayerMap, + Map<Cluster, List<ShowerBranch>> clusterToShowerCandidateMap, + Map<ShowerBranch, List<Cluster>> showerToClusterCandidateMap) { + + + /* --------- */ printDebug("createCandidateAssociations() called with "+ /* --------- */ + /* --------- */ clusterSlicesOnThisLayer.size()+" clusters and "+ /* --------- */ + /* --------- */ reconstructedShowers.size()+" previously reconstructed showers"); /* --------- */ + + + /* --------- */ printDebug("Start loop on clusters"); /* --------- */ + + + // find candidates for associations + for( Cluster clus2D : clusterSlicesOnThisLayer ) { + + // get the layer for this cluster + PFADetectorLayer layer = clusterSliceToLayerMap.get(clus2D); + if(layer == null) throw new AssertionError("book-keeping error"); + + + /* --------- */ printDebug("Finding candidate assotiations for cluster with "+ /* --------- */ + /* --------- */ clus2D.getCalorimeterHits().size()+" hits on layer "+layer.id()); /* --------- */ + + + /* --------- */ printDebug("Start loop on showers"); /* --------- */ + + + // loop on shower branches + for( ShowerWithBranches shower : reconstructedShowers ) { + + + /* --------- */ printDebug("Shower has "+shower.getBranches().size()+" branch"); /* --------- */ + /* --------- */ printDebug("Start loop on branches"); /* --------- */ + + + for( ShowerBranch branch : shower.getBranches() ) { + + + /* --------- */ printDebug("Shower branch has "+branch.getClusters().size()+" already assigned clusters"); /* --------- */ + + + // get the last added cluster to the shower and the corresponding layer + Cluster lastAddedClus = branch.getLastAddedCluster(); + PFADetectorLayer lastAddedLayer = clusterSliceToLayerMap.get(lastAddedClus); + if(lastAddedLayer == null) throw new AssertionError("book-keeping error: "); + + + /* --------- */ printDebug("Last added cluster has "+lastAddedClus.getCalorimeterHits().size()+" hits and was on layer "+lastAddedLayer.id()); /* --------- */ + + + // take the decision to connect or not + if(isGoodCandidateAssociation( lastAddedClus, clus2D)) { + + + /* --------- */ printDebug("Decision was in favor of connecting to this branch: proceed with this branch"); /* --------- */ + /* --------- */ printDebug("Adding this branch to the list of this cluster's candidates"); /* --------- */ + + + // add to the cluster to shower map + List<ShowerBranch> showersForClus = clusterToShowerCandidateMap.get(clus2D); + if( showersForClus == null ) { + showersForClus = new Vector<ShowerBranch>(); + clusterToShowerCandidateMap.put( clus2D , showersForClus ); + } + + + /* --------- */ printDebug("Cluster already had "+showersForClus.size()+" branch candidates: adding a new one"); /* --------- */ + + + showersForClus.add( branch ); + + + /* --------- */ printDebug("Cluster has "+showersForClus.size()+" branch candidates after adding a this branch"); /* --------- */ + /* --------- */ printDebug("Adding this cluster to the list of this branche's candidates"); /* --------- */ + + + // add to the shower to cluster map + List<Cluster> clustersForShower = showerToClusterCandidateMap.get( branch ); + if( clustersForShower == null ) { + clustersForShower = new Vector<Cluster>(); + showerToClusterCandidateMap.put( branch , clustersForShower ); + } + + + /* --------- */ printDebug("Branch already had "+clustersForShower.size()+" cluster candidates: adding a new one"); /* --------- */ + + + clustersForShower.add( clus2D ); + + + /* --------- */ printDebug("Branch has "+clustersForShower.size()+" cluster candidates after addind this cluster"); /* --------- */ + + + } else { + + + /* --------- */ printDebug("Decision was not in favor of connecting to this branch: proceed to next branch"); /* --------- */ + + + } + } + + + /* --------- */ printDebug("Done with loop on branches for this shower"); /* --------- */ + + + } + + + /* --------- */ printDebug("Done with loop on showers for this cluster"); /* --------- */ + + + } + + + /* --------- */ printDebug("Done with loop on clusters: leaving createCandidateAssociations()"); /* --------- */ + + + } + + + /** + * Resolve cases where a cluster is assigned to multiple showers + * as well as cases where multiple clusters are assigned to the same shower + */ + protected void resolveAmbiguities( List<Cluster> clusterSlicesOnNextLayer, + Map<Cluster, List<ShowerBranch>> clusterToShowerCandidateMap, + Map<ShowerBranch, List<Cluster>> showerToClusterCandidateMap ) + { + + // first make lists of concurrent connections + List< List<ConnectionCandidate> > concurrentConnectionsLists = getConcurrentConnections( clusterToShowerCandidateMap, showerToClusterCandidateMap ); + + // loop on concurrent connections lists and resolve ambiguities + for(List<ConnectionCandidate> concurrentConnections : concurrentConnectionsLists) { + + // resolve the ambiguities + List<ConnectionCandidate> resolvedConnections = resolveConcurrentConnections(concurrentConnections, + clusterToShowerCandidateMap, + showerToClusterCandidateMap, + clusterSlicesOnNextLayer ); + + // remove vetoed connections from the input maps + List<ConnectionCandidate> vetoedConnections = new Vector<ConnectionCandidate>(); + vetoedConnections.addAll(concurrentConnections); + vetoedConnections.removeAll(resolvedConnections); + for(ConnectionCandidate connection : vetoedConnections) { + + // get the shower branch and the cluster objects + ShowerBranch branch = connection.getBranch(); + Cluster cluster = connection.getCluster(); + + // remove from the cluster to shower branch map + List<ShowerBranch> branchesForCluster = clusterToShowerCandidateMap.get(cluster); + if(branchesForCluster == null) continue; //throw new AssertionError("book-keeping error"); + branchesForCluster.remove(branch); + if(branchesForCluster.size() == 0) { + clusterToShowerCandidateMap.remove(cluster); + } + + // remove from the shower branch to cluster map + List<Cluster> clustersForBranch = showerToClusterCandidateMap.get(branch); + // if(clustersForBranch == null) throw new AssertionError("book-keeping error"); + if(clustersForBranch != null){ + clustersForBranch.remove(cluster); + if(clustersForBranch.size() == 0) { + showerToClusterCandidateMap.remove(branch); + } + } + } + } + } + + + /** + * Performs the association between the clusters and the showers + * All decisions have already been made and this is mainly book-keeping + */ + protected void assignClustersToShowers( List<Cluster> clusterSlicesOnThisLayer, + Map<Cluster, PFADetectorLayer> clusterSliceToLayerMap, + Map<Cluster, List<ShowerBranch>> clusterToShowerCandidateMap, + Map<ShowerBranch, List<Cluster>> showerToClusterCandidateMap ) + { + + // some of the big clusters are assigned to more than one shower + // these clusters have substructure and can be split... + // split these clusters + splitMultiplyAssignedLargeClusters(clusterSlicesOnThisLayer, + clusterSliceToLayerMap, + clusterToShowerCandidateMap, + showerToClusterCandidateMap); + + // loop on shower branches + for(ShowerBranch branch : showerToClusterCandidateMap.keySet()) { + + // get the clusters to be added to the branch + List<Cluster> clustersToAdd = showerToClusterCandidateMap.get(branch); + + // if there is only one cluster, add it to the branch + if(clustersToAdd.size() == 1) { + branch.addCluster(clustersToAdd.get(0)); + } + // if there is more than one cluster, create a separate branch for each + else if(clustersToAdd.size() > 1) { + + // get the branching point from the current branch + Hep3Vector branchingPoint = branch.getPosition(); + + // get the parent shower to which the new branches belong + ShowerWithBranches shower = branch.getMother(); + + // create a new branch for each cluster + for(Cluster clusToAdd : clustersToAdd) { + ShowerBranch newBranch = new ShowerBranch(branchingPoint); + newBranch.addCluster( clusToAdd ); + shower.addBranch( newBranch ); + } + } + // if list is empty, we have made a mistake somewhere + else throw new AssertionError("book-keeping error"); + } + } + + + /** + * shares the leftover hits + */ + protected void shareLeftoverHits(List<ShowerWithBranches> reconstructedShowers, Collection<CalorimeterHit> hitsToShare) + { + + // create bite-sized clusters for the sharing algorithm + List<Cluster> smallClustersToShare = new Vector<Cluster>(); + for (CalorimeterHit hit : hitsToShare) { + BasicCluster tmpClus = new BasicCluster(); + tmpClus.addHit(hit); + smallClustersToShare.add(tmpClus); + } + + // Set up sharing + double maxDistanceForSmallClusters = 250.0; // 25cm isolation cut-off + if (m_properties.getFlag("allowSharingOfIsolatedHits")) { + maxDistanceForSmallClusters = 99999.9; // effectively no cut-off + } + + // get the photons: these will be excluded fron the cone sharing + List<Cluster> photons = (List<Cluster>)m_bookKeeper.getClusterList("Photons"); + + // the linkable clusters: clusters among which the sharing is performed + // --> use the 2D slices + List<Cluster> linkableClusters = new Vector<Cluster>(); + for(ShowerWithBranches shower : reconstructedShowers) { + for(ShowerBranch branch : shower.getBranches()) { + for(Cluster cluster : branch.getClusters()) { + linkableClusters.add(cluster); + } + } + } + + // share clusters: based on proximity and cone + List<SharedClusterGroup> sharedClusters = new Vector<SharedClusterGroup>(); + MultipleClusterSharingAlgorithm proximityAndConeAlg = new MultipleClusterSharingAlgorithm(); + proximityAndConeAlg.addAlgorithm(new ProximityClusterSharingAlgorithm(40.0, maxDistanceForSmallClusters)); + proximityAndConeAlg.addAlgorithm(new ClusterSharingAlgorithmExcludingTargets(new ConeClusterSharingAlgorithm(0.95, 0.90), photons)); + SharedClusterGroup sharedSmallClusters = new SharedClusterGroup(smallClustersToShare, proximityAndConeAlg); + sharedSmallClusters.createShares(linkableClusters); + sharedSmallClusters.rebuildHints(); + sharedClusters.add(sharedSmallClusters); + + // book-keeping: tell the showers about the results + for(ShowerWithBranches shower : reconstructedShowers) { + shower.setSharedClusters(sharedClusters); + } + } + + + /** + * Apply overrides to shower reconstruction + */ + protected void applyOverrides(List<ShowerWithBranches> reconstructedShowers) + { + + /* --------- */ boolean printhere = true; /* --------- */ + + + /* --------- */ printDebug("ApplyOverrides called with "+reconstructedShowers.size()+" showers in input", printhere); /* --------- */ + /* --------- */ for( ShowerWithBranches shower : reconstructedShowers ) { /* --------- */ + /* --------- */ printDebug("Shower "+reconstructedShowers.indexOf(shower)+": "+ /* --------- */ + /* --------- */ "E = "+shower.getRealEnergy()+" "+ /* --------- */ + /* --------- */ "P = "+shower.getMomentum()+" "+ /* --------- */ + /* --------- */ "Layer0 = "+getFirstLayer(shower.getCluster()).id()+" "+ /* --------- */ + /* --------- */ "Layer1 = "+getLastLayer(shower.getCluster()).id(), printhere); /* --------- */ + /* --------- */ } /* --------- */ + + + // categorize showers + Map<ShowerType, List<ShowerWithBranches>> showerTypeToShowerListMap = categorizeShowers(reconstructedShowers); + + + /* --------- */ printDebug("Found "+showerTypeToShowerListMap.get(ShowerType.ST_FRAGMENT).size()+" showers of type ST_FRAGMENT", printhere); /* --------- */ + /* --------- */ printDebug("Found "+showerTypeToShowerListMap.get(ShowerType.ST_NEUTRAL).size()+" showers of type ST_NEUTRAL", printhere); /* --------- */ + /* --------- */ printDebug("Found "+showerTypeToShowerListMap.get(ShowerType.ST_CHARGED_INNEED).size()+" showers of type ST_CHARGED_INNEED", printhere); /* --------- */ + /* --------- */ printDebug("Found "+showerTypeToShowerListMap.get(ShowerType.ST_CHARGED_SATISFIED).size()+" showers of type ST_CHARGED_SATISFIED", printhere); /* --------- */ + /* --------- */ printDebug("Found "+showerTypeToShowerListMap.get(ShowerType.ST_CHARGED_OVERSTUFFED).size()+" showers of type ST_CHARGED_OVERSTUFFED", printhere); /* --------- */ + + + // loop on tiny shower fragments and assign them to the closest non-tiny shower + for(ShowerWithBranches tinyShower : showerTypeToShowerListMap.get(ShowerType.ST_FRAGMENT)) { + + // tiny shower position + Hep3Vector tinyShowerPos = new BasicHep3Vector(tinyShower.getCluster().getPosition()); + + // best shower to connect to + double bestCosAngle = m_maxCosAngleToConnectTinyShowers; + ShowerWithBranches bestShower = null; + + // loop on reconstructed showers to find best match + for(ShowerWithBranches shower : reconstructedShowers) { + + // don't connect to another tiny shower + if(showerTypeToShowerListMap.get(ShowerType.ST_FRAGMENT).contains(shower)) continue; + + // shower position + Hep3Vector showerPos = new BasicHep3Vector(shower.getCluster().getPosition()); + + // connect based on angle + double cosAngle = VecOp.dot(VecOp.unit(showerPos), VecOp.unit(tinyShowerPos)); + if(cosAngle > bestCosAngle) { + bestCosAngle = cosAngle; + bestShower = shower; + } + } + + // if a best match was found: connect to it + if(bestShower != null) { + for(ShowerBranch branch : tinyShower.getBranches()) { + bestShower.addBranch(branch); + } + reconstructedShowers.remove(tinyShower); + } + } + + + /* --------- */ printDebug("After tiny showers: "+reconstructedShowers.size()+" showerst", printhere); /* --------- */ + /* --------- */ for( ShowerWithBranches shower : reconstructedShowers ) { /* --------- */ + /* --------- */ printDebug("Shower "+reconstructedShowers.indexOf(shower)+": "+ /* --------- */ + /* --------- */ "E = "+shower.getRealEnergy()+" "+ /* --------- */ + /* --------- */ "P = "+shower.getMomentum()+" "+ /* --------- */ + /* --------- */ "Layer0 = "+getFirstLayer(shower.getCluster()).id()+" "+ /* --------- */ + /* --------- */ "Layer1 = "+getLastLayer(shower.getCluster()).id(), printhere); /* --------- */ + /* --------- */ } /* --------- */ + + + // categorize showers + showerTypeToShowerListMap = categorizeShowers(reconstructedShowers); + + + /* --------- */ printDebug("After tiny showers: Found "+showerTypeToShowerListMap.get(ShowerType.ST_FRAGMENT).size()+" showers of type ST_FRAGMENT", printhere); /* --------- */ + /* --------- */ printDebug("After tiny showers: Found "+showerTypeToShowerListMap.get(ShowerType.ST_NEUTRAL).size()+" showers of type ST_NEUTRAL", printhere); /* --------- */ + /* --------- */ printDebug("After tiny showers: Found "+showerTypeToShowerListMap.get(ShowerType.ST_CHARGED_INNEED).size()+" showers of type ST_CHARGED_INNEED", printhere); /* --------- */ + /* --------- */ printDebug("After tiny showers: Found "+showerTypeToShowerListMap.get(ShowerType.ST_CHARGED_SATISFIED).size()+" showers of type ST_CHARGED_SATISFIED", printhere); /* --------- */ + /* --------- */ printDebug("After tiny showers: Found "+showerTypeToShowerListMap.get(ShowerType.ST_CHARGED_OVERSTUFFED).size()+" showers of type ST_CHARGED_OVERSTUFFED", printhere); /* --------- */ + + List<ShowerWithBranches> smallBranches = new Vector<ShowerWithBranches>(); + while(reconstructedShowers.size() > 8) { + ShowerWithBranches theSmallest = null; + for(ShowerWithBranches shower : reconstructedShowers) { + if(shower.isCharged()) continue; + if(theSmallest == null || shower.getRealEnergy() < theSmallest.getRealEnergy()) { + theSmallest = shower; + } + } + if(theSmallest == null) break; + reconstructedShowers.remove(theSmallest); + smallBranches.add(theSmallest); + } + + List<List<List<ShowerWithBranches>>> allCombinations = makeAllGroupCombinations(reconstructedShowers); + + List<List<ShowerWithBranches>> bestCombination = null; + double bestCombinationFigureOfMerit = 0; + for(List<List<ShowerWithBranches>> aCombination : allCombinations) { + double combinationFigureOfMerit = getCombinationFigureOfMerit(aCombination); + if(combinationFigureOfMerit > bestCombinationFigureOfMerit) { + bestCombinationFigureOfMerit = combinationFigureOfMerit; + bestCombination = aCombination; + } + } + + if(bestCombination != null) { + for(List<ShowerWithBranches> aGroup : bestCombination) { + ShowerWithBranches base = null; + for(ShowerWithBranches shower : aGroup) { + if(shower.isCharged()) { + base = shower; + break; + } + } + for(ShowerWithBranches shower : aGroup) { + if(base == null) { + base = shower; + }else if(shower != base){ + reconstructedShowers.remove(shower); + for(ShowerBranch branch : shower.getBranches()) { + base.addBranch(branch); + } + for(Track track : shower.getTracks()) { + base.addTrack(track); + } + } + } + } + } + + reconstructedShowers.addAll(smallBranches); + + + /* --------- */ printDebug("After reconnections: "+reconstructedShowers.size()+" showerst", printhere); /* --------- */ + /* --------- */ for( ShowerWithBranches shower : reconstructedShowers ) { /* --------- */ + /* --------- */ printDebug("Shower "+reconstructedShowers.indexOf(shower)+": "+ /* --------- */ + /* --------- */ "E = "+shower.getRealEnergy()+" "+ /* --------- */ + /* --------- */ "P = "+shower.getMomentum()+" "+ /* --------- */ + /* --------- */ "Layer0 = "+getFirstLayer(shower.getCluster()).id()+" "+ /* --------- */ + /* --------- */ "Layer1 = "+getLastLayer(shower.getCluster()).id(), printhere); /* --------- */ + /* --------- */ } /* --------- */ + + + // categorize showers + showerTypeToShowerListMap = categorizeShowers(reconstructedShowers); + + + /* --------- */ printDebug("After reconnections: Found "+showerTypeToShowerListMap.get(ShowerType.ST_FRAGMENT).size()+" showers of type ST_FRAGMENT", printhere); /* --------- */ + /* --------- */ printDebug("After reconnections: Found "+showerTypeToShowerListMap.get(ShowerType.ST_NEUTRAL).size()+" showers of type ST_NEUTRAL", printhere); /* --------- */ + /* --------- */ printDebug("After reconnections: Found "+showerTypeToShowerListMap.get(ShowerType.ST_CHARGED_INNEED).size()+" showers of type ST_CHARGED_INNEED", printhere); /* --------- */ + /* --------- */ printDebug("After reconnections: Found "+showerTypeToShowerListMap.get(ShowerType.ST_CHARGED_SATISFIED).size()+" showers of type ST_CHARGED_SATISFIED", printhere); /* --------- */ + /* --------- */ printDebug("After reconnections: Found "+showerTypeToShowerListMap.get(ShowerType.ST_CHARGED_OVERSTUFFED).size()+" showers of type ST_CHARGED_OVERSTUFFED", printhere); /* --------- */ + + } + + + /** + * Calculates a figure of merit for aa combination + */ + protected double getCombinationFigureOfMerit(List<List<ShowerWithBranches>> aCombination) + { + + for(List<ShowerWithBranches> aGroup : aCombination) { + boolean isAllNeutral = true; + for(ShowerWithBranches aShower : aGroup) { + if(aShower.isCharged()) { + isAllNeutral = false; + break; + } + } + if(isAllNeutral && aGroup.size() > 1) { + return -1; + } + } + + double figureOfMerit = 1; + double nChargedGroup = 0; + + for(List<ShowerWithBranches> aGroup : aCombination) { + boolean isAllNeutral = true; + for(ShowerWithBranches aShower : aGroup) { + if(aShower.isCharged()) { + isAllNeutral = false; + break; + } + } + if(isAllNeutral) { + continue; + } + ShowerWithBranches combinedShower = new ShowerWithBranches(m_chargedCalib); + for(ShowerWithBranches shower : aGroup) { + for(ShowerBranch branch : shower.getBranches()) { + combinedShower.addBranch(branch); + } + for(Track track : shower.getTracks()) { + combinedShower.addTrack(track); + } + combinedShower.setSharedClusters(shower.getSharedClusters()); + } + + double energyFromInDet = combinedShower.getMomentum(); + double energyFromCalo = combinedShower.getRealEnergy(); + double energyUncertainty = combinedShower.getEnergyUncertainty(); + + double energyResidual = (energyFromCalo - energyFromInDet) / energyUncertainty; + + double probEoverP = 2 * Erf.phic(Math.abs(energyResidual)); + + figureOfMerit *= probEoverP; + nChargedGroup += 1; + + + /* --------- */ printDebug("Combination: E = "+energyFromCalo+" P = "+energyFromInDet+" S = "+energyUncertainty+" R = "+energyResidual+" p = "+probEoverP); /* --------- */ + } + + + if(nChargedGroup < 1) { + return figureOfMerit; + } + + return Math.pow(figureOfMerit, 1/nChargedGroup); + } + + + /** + * make all possible combinations on grouping showers + */ + protected List<List<List<ShowerWithBranches>>> makeAllGroupCombinations(List<ShowerWithBranches> reconstructedShowers) + { + + List<List<ShowerWithBranches>> theFlatPartition = new Vector<List<ShowerWithBranches>>();[truncated at 1000 lines; 2758 more skipped]
diff -u -r1.2 -r1.3 --- BaselineShowerBuilder.java 23 Oct 2011 09:50:31 -0000 1.2 +++ BaselineShowerBuilder.java 11 Apr 2012 15:49:36 -0000 1.3 @@ -9,12 +9,14 @@
import org.lcsim.util.swim.*; import org.lcsim.util.hitmap.*; import org.lcsim.mc.fast.tracking.*;
-import org.lcsim.recon.pfa.identifier.*;
+import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.*;
import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.structural.sharing.*; import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.structural.shower.*; import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.debug.*; import org.lcsim.geometry.subdetector.*; import org.lcsim.geometry.*;
+import org.lcsim.recon.util.CalorimeterInformation; +import org.lcsim.geometry.Calorimeter.CalorimeterType;
public class BaselineShowerBuilder implements IShowerBuilder {
@@ -94,7 +96,8 @@
Map<Track, Set<Track>> mapTrackToJet = null; // Iterate to build clusters:
- for (int iIter=0; iIter<10; iIter++) {
+ int nIter = (int)m_properties.getCut("numberOfShowerBuildingIterations"); + for (int iIter=0; iIter<nIter; iIter++) {
// newMapShowerComponentToTrack.clear(); // newMapTrackToShowerComponents.clear(); // newMapTrackToVetoedAdditions.clear();
@@ -1689,11 +1692,9 @@
} protected int countHitsInLastLayersOfHcal(Collection<Cluster> clusters, int nLayersToCheck) { // Pick up detector geometry
- Detector det = m_event.getDetector(); - CylindricalCalorimeter hadBarrel = ((CylindricalCalorimeter) det.getSubdetectors().get("HADBarrel")); - CylindricalCalorimeter hadEndcap = ((CylindricalCalorimeter) det.getSubdetectors().get("HADEndcap")); - int nLayersHadBarrel = hadBarrel.getLayering().getLayerCount(); - int nLayersHadEndcap = hadEndcap.getLayering().getLayerCount();
+ CalorimeterInformation ci = CalorimeterInformation.instance(); + int nLayersHadBarrel = ci.getNLayers(CalorimeterType.HAD_BARREL); + int nLayersHadEndcap = ci.getNLayers(CalorimeterType.HAD_ENDCAP);
// Scan for hits Set<Long> hitsFoundInLastLayersOfHcal = new HashSet<Long>();
@@ -1723,13 +1724,12 @@
} protected int countHitsInSideEdgesOfHcal(Cluster clus, int nLayersToCheck) { // Pick up detector geometry
- Detector det = m_event.getDetector(); - CylindricalCalorimeter hadBarrel = ((CylindricalCalorimeter) det.getSubdetectors().get("HADBarrel")); - double backZ = hadBarrel.getZMax(); - double innerRadius = hadBarrel.getInnerRadius();
+ CalorimeterInformation ci = CalorimeterInformation.instance(); + double backZ = ci.getZMax(CalorimeterType.HAD_BARREL); + double innerRadius = ci.getRMin(CalorimeterType.HAD_BARREL);
double tanTheta = innerRadius/backZ;
- org.lcsim.geometry.IDDecoder id = hadBarrel.getIDDecoder();
+ IDDecoder id = ci.getIDDecoder(CalorimeterType.HAD_BARREL);
if (id instanceof org.lcsim.geometry.segmentation.NonprojectiveCylinder) { org.lcsim.geometry.segmentation.NonprojectiveCylinder segmentation = (org.lcsim.geometry.segmentation.NonprojectiveCylinder) id; double gridZ = segmentation.getGridSizeZ();
diff -u -r1.2 -r1.3 --- ChargedHadronClusterEnergyCalculator.java 23 Oct 2011 09:50:31 -0000 1.2 +++ ChargedHadronClusterEnergyCalculator.java 11 Apr 2012 15:49:36 -0000 1.3 @@ -18,7 +18,7 @@
* * @author Mat Charles <[log in to unmask]> *
- * @version $Id: ChargedHadronClusterEnergyCalculator.java,v 1.2 2011/10/23 09:50:31 zaidan Exp $
+ * @version $Id: ChargedHadronClusterEnergyCalculator.java,v 1.3 2012/04/11 15:49:36 zaidan Exp $
*/ public class ChargedHadronClusterEnergyCalculator extends Driver implements ClusterEnergyCalculator
diff -u -r1.2 -r1.3 --- CheckDisjoint.java 23 Oct 2011 09:50:31 -0000 1.2 +++ CheckDisjoint.java 11 Apr 2012 15:49:36 -0000 1.3 @@ -8,7 +8,7 @@
import org.lcsim.recon.cluster.directedtree.*; import org.lcsim.util.hitmap.*; import org.lcsim.util.decision.*;
-import org.lcsim.recon.pfa.identifier.*;
+import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.*;
/** * Validation driver to check that two collections/hitmaps are disjoint.
@@ -17,7 +17,7 @@
* 2) A Collection of Cluster objects * 3) A HitMap *
- * @version $Id: CheckDisjoint.java,v 1.2 2011/10/23 09:50:31 zaidan Exp $
+ * @version $Id: CheckDisjoint.java,v 1.3 2012/04/11 15:49:36 zaidan Exp $
* @author [log in to unmask] */
diff -u -r1.1 -r1.2 --- CheckSkeletonsForMultipleTracks.java 27 May 2011 12:01:11 -0000 1.1 +++ CheckSkeletonsForMultipleTracks.java 11 Apr 2012 15:49:36 -0000 1.2 @@ -10,7 +10,7 @@
import org.lcsim.event.util.*; import org.lcsim.contrib.uiowa.uiowapfa.recon.cluster.structural.likelihood.*; import org.lcsim.recon.cluster.util.BasicCluster;
-import org.lcsim.recon.pfa.identifier.TrackClusterMatcher;
+import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.TrackClusterMatcher;
public class CheckSkeletonsForMultipleTracks extends Driver {
diff -u -r1.2 -r1.3 --- ConeMIPReassignmentAlgorithm.java 23 Oct 2011 09:50:31 -0000 1.2 +++ ConeMIPReassignmentAlgorithm.java 11 Apr 2012 15:49:36 -0000 1.3 @@ -13,7 +13,7 @@
* the track at its showering point. We then calculate the angle * between the tangent and the vector from the apex to the cluster. *
- * @version $Id: ConeMIPReassignmentAlgorithm.java,v 1.2 2011/10/23 09:50:31 zaidan Exp $
+ * @version $Id: ConeMIPReassignmentAlgorithm.java,v 1.3 2012/04/11 15:49:36 zaidan Exp $
*/ public class ConeMIPReassignmentAlgorithm implements ReassignClustersAlgorithm {
diff -u -r1.1 -r1.2 --- ConeReassignmentAlgorithm.java 27 May 2011 12:01:11 -0000 1.1 +++ ConeReassignmentAlgorithm.java 11 Apr 2012 15:49:36 -0000 1.2 @@ -5,7 +5,7 @@
import org.lcsim.event.util.*; import org.lcsim.event.*; import hep.physics.vec.*;
-import org.lcsim.recon.pfa.identifier.*;
+import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.*;
public class ConeReassignmentAlgorithm implements ReassignClustersAlgorithm { protected double m_limit;
diff -u -r1.2 -r1.3 --- ExampleGenerateLikelihood.java 23 Oct 2011 09:50:31 -0000 1.2 +++ ExampleGenerateLikelihood.java 11 Apr 2012 15:49:36 -0000 1.3 @@ -17,7 +17,7 @@
* energy. * * @author Mat <[log in to unmask]>
- * @version $Id: ExampleGenerateLikelihood.java,v 1.2 2011/10/23 09:50:31 zaidan Exp $
+ * @version $Id: ExampleGenerateLikelihood.java,v 1.3 2012/04/11 15:49:36 zaidan Exp $
*/ public class ExampleGenerateLikelihood extends Driver
diff -u -r1.2 -r1.3 --- FuzzyCalorimeterHit.java 23 Oct 2011 09:50:31 -0000 1.2 +++ FuzzyCalorimeterHit.java 11 Apr 2012 15:49:36 -0000 1.3 @@ -9,7 +9,7 @@
* Watch out! Regular calibrations won't look at the weight and will over-count * the hit's energy. *
- * @version $Id: FuzzyCalorimeterHit.java,v 1.2 2011/10/23 09:50:31 zaidan Exp $
+ * @version $Id: FuzzyCalorimeterHit.java,v 1.3 2012/04/11 15:49:36 zaidan Exp $
*/ public class FuzzyCalorimeterHit
diff -u -r1.2 -r1.3 --- FuzzyNeutralHadronClusterEnergyCalculator.java 23 Oct 2011 09:50:31 -0000 1.2 +++ FuzzyNeutralHadronClusterEnergyCalculator.java 11 Apr 2012 15:49:36 -0000 1.3 @@ -14,7 +14,7 @@
* an extension of Ron's DetailedNeutralHadronClusterEnergyCalculator * class. *
- * @version $Id: FuzzyNeutralHadronClusterEnergyCalculator.java,v 1.2 2011/10/23 09:50:31 zaidan Exp $
+ * @version $Id: FuzzyNeutralHadronClusterEnergyCalculator.java,v 1.3 2012/04/11 15:49:36 zaidan Exp $
*/ public class FuzzyNeutralHadronClusterEnergyCalculator extends DetailedNeutralHadronClusterEnergyCalculator
diff -u -r1.2 -r1.3 --- FuzzyPhotonClusterEnergyCalculator.java 23 Oct 2011 09:50:31 -0000 1.2 +++ FuzzyPhotonClusterEnergyCalculator.java 11 Apr 2012 15:49:36 -0000 1.3 @@ -14,7 +14,7 @@
* an extension of Ron's PhotonClusterEnergyCalculator * class. *
- * @version $Id: FuzzyPhotonClusterEnergyCalculator.java,v 1.2 2011/10/23 09:50:31 zaidan Exp $
+ * @version $Id: FuzzyPhotonClusterEnergyCalculator.java,v 1.3 2012/04/11 15:49:36 zaidan Exp $
*/ public class FuzzyPhotonClusterEnergyCalculator extends PhotonClusterEnergyCalculator
diff -u -r1.2 -r1.3 --- FuzzyQNeutralHadronClusterEnergyCalculator.java 23 Oct 2011 09:50:31 -0000 1.2 +++ FuzzyQNeutralHadronClusterEnergyCalculator.java 11 Apr 2012 15:49:36 -0000 1.3 @@ -14,7 +14,7 @@
* an extension of Ron's QNeutralHadronClusterEnergyCalculator * class. *
- * @version $Id: FuzzyQNeutralHadronClusterEnergyCalculator.java,v 1.2 2011/10/23 09:50:31 zaidan Exp $
+ * @version $Id: FuzzyQNeutralHadronClusterEnergyCalculator.java,v 1.3 2012/04/11 15:49:36 zaidan Exp $
*/ public class FuzzyQNeutralHadronClusterEnergyCalculator extends QNeutralHadronClusterEnergyCalculator
diff -u -r1.2 -r1.3 --- FuzzyQPhotonClusterEnergyCalculator.java 23 Oct 2011 09:50:31 -0000 1.2 +++ FuzzyQPhotonClusterEnergyCalculator.java 11 Apr 2012 15:49:36 -0000 1.3 @@ -13,7 +13,7 @@
* clusters such that the total weight adds up to 1. This is * an extension of Ron's QPhotonClusterEnergyCalculator class. *
- * @version $Id: FuzzyQPhotonClusterEnergyCalculator.java,v 1.2 2011/10/23 09:50:31 zaidan Exp $
+ * @version $Id: FuzzyQPhotonClusterEnergyCalculator.java,v 1.3 2012/04/11 15:49:36 zaidan Exp $
*/ public class FuzzyQPhotonClusterEnergyCalculator extends QPhotonClusterEnergyCalculator
diff -u -r1.2 -r1.3 --- HelixTangentMIPGeometryHandler.java 23 Oct 2011 09:50:31 -0000 1.2 +++ HelixTangentMIPGeometryHandler.java 11 Apr 2012 15:49:36 -0000 1.3 @@ -5,7 +5,7 @@
import org.lcsim.event.util.*; import org.lcsim.event.*; import hep.physics.vec.*;
-import org.lcsim.recon.pfa.identifier.*;
+import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.*;
import org.lcsim.recon.cluster.util.BasicCluster; import org.lcsim.geometry.*;
@@ -20,7 +20,7 @@
* The calculation is based on identifying the outermost hit * and then checking the track helix near that point. *
- * @version $Id: HelixTangentMIPGeometryHandler.java,v 1.2 2011/10/23 09:50:31 zaidan Exp $
+ * @version $Id: HelixTangentMIPGeometryHandler.java,v 1.3 2012/04/11 15:49:36 zaidan Exp $
*/ public class HelixTangentMIPGeometryHandler extends MIPGeometryHandler {
diff -u -r1.2 -r1.3 --- HitBookKeeper.java 23 Oct 2011 09:50:31 -0000 1.2 +++ HitBookKeeper.java 11 Apr 2012 15:49:36 -0000 1.3 @@ -24,7 +24,7 @@
* second group might be a list of clusters plus a * HitMap of left-over hits. *
- * @version $Id: HitBookKeeper.java,v 1.2 2011/10/23 09:50:31 zaidan Exp $
+ * @version $Id: HitBookKeeper.java,v 1.3 2012/04/11 15:49:36 zaidan Exp $
*/ public class HitBookKeeper extends Driver
diff -u -r1.2 -r1.3 --- HitFilterDriver.java 23 Oct 2011 09:50:31 -0000 1.2 +++ HitFilterDriver.java 11 Apr 2012 15:49:36 -0000 1.3 @@ -10,7 +10,7 @@
* This class takes in a List<CalorimeterHit> and * filter it according to user filter options *
- * @version $Id: HitFilterDriver.java,v 1.2 2011/10/23 09:50:31 zaidan Exp $
+ * @version $Id: HitFilterDriver.java,v 1.3 2012/04/11 15:49:36 zaidan Exp $
*/ public class HitFilterDriver extends Driver
diff -u -r1.2 -r1.3 --- LayerBasedMIPGeometryHandler.java 23 Oct 2011 09:50:31 -0000 1.2 +++ LayerBasedMIPGeometryHandler.java 11 Apr 2012 15:49:36 -0000 1.3 @@ -3,7 +3,7 @@
import java.util.*; import org.lcsim.event.*; import hep.physics.vec.*;
-import org.lcsim.recon.pfa.identifier.*;
+import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.*;
import org.lcsim.recon.cluster.util.BasicCluster; import org.lcsim.geometry.*; import org.lcsim.recon.util.CalorimeterInformation;
@@ -23,7 +23,7 @@
* from the IP, then finding the hits in the outermost layer * of that subdetector. *
- * @version $Id: LayerBasedMIPGeometryHandler.java,v 1.2 2011/10/23 09:50:31 zaidan Exp $
+ * @version $Id: LayerBasedMIPGeometryHandler.java,v 1.3 2012/04/11 15:49:36 zaidan Exp $
*/ public class LayerBasedMIPGeometryHandler extends MIPGeometryHandler {
diff -u -r1.2 -r1.3 --- MIPGeometryHandler.java 23 Oct 2011 09:50:31 -0000 1.2 +++ MIPGeometryHandler.java 11 Apr 2012 15:49:36 -0000 1.3 @@ -10,7 +10,7 @@
* that point. Implementation is delegated to * subclasses. *
- * @version $Id: MIPGeometryHandler.java,v 1.2 2011/10/23 09:50:31 zaidan Exp $
+ * @version $Id: MIPGeometryHandler.java,v 1.3 2012/04/11 15:49:36 zaidan Exp $
*/ public abstract class MIPGeometryHandler {
diff -u -r1.2 -r1.3 --- MergeClustersCrossingSubDetectorBoundaries.java 23 Oct 2011 09:50:31 -0000 1.2 +++ MergeClustersCrossingSubDetectorBoundaries.java 11 Apr 2012 15:49:36 -0000 1.3 @@ -14,7 +14,7 @@
* An algorithm to merge clusters that get split because crossing * subdetector boundaries. *
- * @version $Id: MergeClustersCrossingSubDetectorBoundaries.java,v 1.2 2011/10/23 09:50:31 zaidan Exp $
+ * @version $Id: MergeClustersCrossingSubDetectorBoundaries.java,v 1.3 2012/04/11 15:49:36 zaidan Exp $
* @author Remi Zaidan <[log in to unmask]> */
diff -u -r1.1 -r1.2 --- NewShowerBuilder.java 23 Oct 2011 09:50:31 -0000 1.1 +++ NewShowerBuilder.java 11 Apr 2012 15:49:36 -0000 1.2 @@ -1,16 +1,17 @@
package org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.structural; import java.util.*;
+import java.io.IOException;
import hep.physics.vec.*; import org.lcsim.event.*; import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.structural.shower.*; import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.structural.sharing.*;
-import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.debug.*;
import org.lcsim.recon.cluster.util.*; import org.lcsim.recon.util.CalorimeterInformation; import org.lcsim.geometry.Calorimeter.CalorimeterType;
-import org.lcsim.recon.pfa.identifier.*;
+import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.debug.*; +import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.*;
import org.lcsim.util.*; import org.lcsim.util.lcio.LCIOConstants;
@@ -20,6 +21,9 @@
import org.lcsim.math.probability.Erf;
+ + +
public class NewShowerBuilder implements IShowerBuilder { protected PropertyContainer m_properties;
@@ -28,8 +32,8 @@
protected LinkDecisions.LinkDecision m_linkDecision; protected LinkDecisions.LinkDecision m_linkBreakDecision; protected LinkDecisions.LinkDecision m_linkDecisionPhaseSpace;
- protected LinkDecisions.LinkDecision m_linkDecisionPrimary; // alpha - protected LinkDecisions.LinkDecision m_linkDecisionSecondary; // alpha
+ protected LinkDecisions.LinkDecision m_linkDecisionPrimary; + protected LinkDecisions.LinkDecision m_linkDecisionSecondary;
protected ILikelihoodEvaluator m_primaryShowerEval = null; protected ILikelihoodEvaluator m_showerToShowerEval = null;
@@ -41,10 +45,10 @@
protected ClusterEnergyCalculator m_chargedCalib; protected ClusterEnergyCalculator m_neutralCalib;
- protected DebugUtils m_debugUtils; - protected LinkQualityChecker m_LQChecker;
- protected ILikelihoodEvaluator m_eval;
+ DebugUtils m_debugUtils; //gamma + LinkQualityChecker m_LQChecker; //gamma +
/** * Constructor
@@ -61,21 +65,6 @@
m_neutralCalib = neutralCalib; m_extrapolator = extrapolator;
- CalorimeterInformation ci = CalorimeterInformation.instance(); - - //---- Configure MC-truth checking - String mcListName = m_properties.getKey("MCListName"); - String EcalDigiHitMapName = m_properties.getKey("EcalDigiHitMapName"); - String HcalDigiHitMapName = m_properties.getKey("HcalDigiHitMapName"); - - m_debugUtils = new DebugUtils(); - m_debugUtils.setMCListName(mcListName); - m_debugUtils.setEcalDigiHitMapName(EcalDigiHitMapName); - m_debugUtils.setHcalDigiHitMapName(HcalDigiHitMapName); - m_debugUtils.setEnergyBased(true); - - m_LQChecker = new DominantParticleBasedLQChecker(m_debugUtils); -
if(!m_properties.getFlag("makeShowerLikelihoodPDF")) { m_primaryShowerEval = new LikelihoodEvaluatorWrapper( m_properties.getKey("showerLikelihoodPath") );
@@ -101,29 +90,25 @@
}else{ // score & outgoing m_linkBreakDecision = new LinkDecisions.ScoreBasedLinkDecision(m_properties.getCut("scoreCut"));
+ m_linkDecision = new LinkDecisions.OutgoingLinkDecision();
m_linkDecisionPhaseSpace = new LinkDecisions.AngleAtCenterBasedLinkDecision( m_properties.getCut("angleForLinkingCut") );
- List<LinkDecisions.LinkDecision> decisions = new Vector<LinkDecisions.LinkDecision>(); - decisions.add(new LinkDecisions.OutgoingLinkDecision()); - List<String> ecalNames = new Vector<String>(); - ecalNames.add(ci.getName(CalorimeterType.EM_BARREL)); - ecalNames.add(ci.getName(CalorimeterType.EM_ENDCAP)); - LinkDecisions.LinkDecision ecalLinkDecision = new LinkDecisions.SubdetectorBasedLinkDecision(ecalNames); - List<String> hcalNames = new Vector<String>(); - hcalNames.add(ci.getName(CalorimeterType.HAD_BARREL)); - hcalNames.add(ci.getName(CalorimeterType.HAD_ENDCAP)); - hcalNames.add(ci.getName(CalorimeterType.MUON_ENDCAP)); - LinkDecisions.LinkDecision hcalLinkDecision = new LinkDecisions.SubdetectorBasedLinkDecision(hcalNames); - List<LinkDecisions.LinkDecision> subDetectorDecisions = new Vector<LinkDecisions.LinkDecision>(); - subDetectorDecisions.add(ecalLinkDecision); - subDetectorDecisions.add(hcalLinkDecision); - // decisions.add(new LinkDecisions.OrLinkDecision(subDetectorDecisions)); - m_linkDecision = new LinkDecisions.AndLinkDecision(decisions);
}
- m_eval = new LikelihoodEvaluatorWrapper(m_properties.getKey("LikelihoodPath")); - - // alpha
m_linkDecisionPrimary = new LinkDecisions.LikelihoodBasedLinkDecision( m_primaryShowerEval , m_properties.getCut( "primaryShowerScoreCut" ) , "PrimaryShower" );
+ + + + + m_debugUtils = new DebugUtils(); //gamma + m_debugUtils.setMCListName( m_properties.getKey( "MCListName" ) ); //gamma + m_debugUtils.setEcalDigiHitMapName( m_properties.getKey( "EcalDigiHitMapName" ) ); //gamma + m_debugUtils.setHcalDigiHitMapName( m_properties.getKey( "HcalDigiHitMapName" ) ); //gamma + m_debugUtils.setEnergyBased( true ); //gamma + + m_LQChecker = new DominantParticleBasedLQChecker(m_debugUtils); //gamma + + +
}
@@ -132,15 +117,21 @@
*/ public void buildChargedHadronShowers(){
- m_debugUtils.setEventInfo(m_bookKeeper.getEvent()); - List<StructuralLikelihoodQuantity> quantities = m_eval.getLikelihoodQuantities(); - for(StructuralLikelihoodQuantity quantity : quantities){ - quantity.setEventInfo(m_bookKeeper.getEvent()); - }
+ m_debugUtils.setEventInfo( m_bookKeeper.getEvent() );
// do a first iteration: build skeletons m_showerContainer = new ShowerContainer(); chargedHadronsFirstIteration();
+ + // create the shower container + m_showerContainer = new ShowerContainer(); + + // do a first iteration: build skeletons + chargedHadronsFirstIteration(true); + + // do a first iteration: build skeletons + m_showerContainer = new ShowerContainer(); + chargedHadronsFirstIteration(false);
if(!m_properties.getFlag("makeShowerLikelihoodPDF")) {
@@ -207,20 +198,219 @@
List<SharedClusterGroup> allSharedClusters = m_bookKeeper.getAllSharedClusters();
- if(m_properties.getFlag("debug")){
+ if(m_properties.getFlag("debug") || true){
System.out.println("ShowerBuilding: event has "+tracks.size()+" tracks and "+m_bookKeeper.getClusterList("Linkable Clusters").size()+" linkable clusters"); }
+
for( Track track : tracks ) {
+ // seed + Cluster seed = tracksMatchedToClusters.get( track ); + if( seed == null ) + { + throw new AssertionError( "Book keeping error" ); + } + + Shower shower = m_showerContainer.createShower( m_chargedCalib , allSharedClusters , track , seed ); + + //gamma + shower.declareFlag( "isPrimary" , true ); + } + + Set<Shower> showers = m_showerContainer.getShowers(); + + if( m_properties.getFlag( "debug" ) ) + { + System.out.println( "ShowerBuilding: created " + showers.size() + " showers" ); + } + + si = 0; + for( Shower shower : showers ) + { + Set<Cluster> seeds = shower.getSeeds(); + + ///// + + ///// + + if( m_properties.getFlag( "debug" ) ) + { + System.out.println( "ShowerBuilding: Shower " + si + " has " + seeds.size() + " seeds and " + shower.size() + " assigned clusters" ); + } + ss = 0; + + + for( Cluster seed : seeds ) + { + if( m_properties.getFlag( "debug" ) ) + { + System.out.println( "ShowerBuilding: assiging clusters to seed " + ss + " which has " + seed.getCalorimeterHits().size() + " hits" ); + } + assignLinksToCluster( seed , shower , m_showerContainer ); + ss++; + } + + /////// + + boolean toSolve = false; + + double residual = ( shower.scalarMomentum() - shower.coreEnergy() ) / shower.estimatedEnergyUncertainty(); + if( residual > 5. ) + { + if( shower.getSeeds().size() == shower.getShowerComponents().size() ) toSolve = true; + } + + toSolve = false; + + if( toSolve ) + { + Set<Track> trks = shower.getTracks(); + + for( Track trk : trks ) + { + + + + for( Cluster clus : m_bookKeeper.getClusterList( "Linkable Clusters" ) ) + { + boolean isOk = false; + + try + { + isOk = m_LQChecker.accept( trk , clus ); + } + catch( LinkDecisions.DecisionCannotBeMadeException e ) + { + isOk = false; + } + + if( isOk ) + { + if( !shower.contains( clus ) ) + { + m_showerContainer.addClusterToShower( shower, clus ); + } + } + + + + /* + MCParticle dominantParticle = m_energyBasedDebugUtils.quoteDominantParticle( clus ); + MCParticle p1 = m_energyBasedDebugUtils.backTrace( dominantParticle ); + + List<MCParticle> mcList = m_energyBasedDebugUtils.getMCParticle( trk ); + + for( MCParticle mc : mcList ) + { + MCParticle p2 = m_energyBasedDebugUtils.backTrace( mc ); + if( p1 == p2 && !isOk ) System.out.println( ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 1" ); + if( p1 != p2 && isOk ) System.out.println( ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 2" ); + } + */ + + + } + } + } + + /////// + /* + if( seeds.size() == shower.getShowerComponents().size() ) + { + double residual = ( shower.scalarMomentum() - shower.coreEnergy() ) / shower.estimatedEnergyUncertainty(); + if( residual > 5. ) + { + Map< Cluster , List<ScoredLink> > potentialLinks = m_bookKeeper.getPotentialLinks(); + for( Cluster seed : seeds ) + { + List<ScoredLink> listScoredLinks = potentialLinks.get( seed ); + if( listScoredLinks != null ) + { + if( listScoredLinks.size() > 0 ) + { + Cluster ClusterWithStrongestLisk = listScoredLinks.get( 0 ).counterpart( seed ); + m_showerContainer.addClusterToShower( shower , ClusterWithStrongestLisk ); + assignLinksToCluster( ClusterWithStrongestLisk , shower , m_showerContainer ); + } + } + } + } + } + */ + /////// + + + if(m_properties.getFlag("debug")){ + System.out.println("ShowerBuilding: After assigning clusters to seeds, shower "+si+" has "+shower.size()+" assigned clusters"); + } + si++; + } + + if(m_properties.getFlag("keepShowerContainersAtEachStep")) { + m_bookKeeper.addShowerContainer("charged showers after first iteration fixing failures", m_showerContainer.clone()); + } + } + + + + + protected void chargedHadronsFirstIteration(boolean useTrack) + { + + MiscUtilities.extrapolator = m_bookKeeper.getExtrapolator(); + MiscUtilities.useTrackDirection = useTrack; + MiscUtilities.clustersMatchedToTracks = m_bookKeeper.getClustersMatchedToTracks(); + + CalorimeterInformation ci = CalorimeterInformation.instance();
+ Map<Track,Cluster> tracksMatchedToClusters = m_bookKeeper.getTracksMatchedToClusters(); + Set<Track> tracks = tracksMatchedToClusters.keySet(); + + List<SharedClusterGroup> allSharedClusters = m_bookKeeper.getAllSharedClusters(); + + if(m_properties.getFlag("debug")){ + System.out.println("ShowerBuilding: event has "+tracks.size()+" tracks and "+m_bookKeeper.getClusterList("Linkable Clusters").size()+" linkable clusters"); + } + + for( Track track : tracks ) + {
// seed
+
Cluster seed = tracksMatchedToClusters.get( track ); if(seed == null){ throw new AssertionError("Book keeping error"); } Shower shower = m_showerContainer.createShower(m_chargedCalib, allSharedClusters, track, seed);
+ + + /* + Cluster seed = null; + Shower shower = null; + + for( Cluster clus : m_bookKeeper.getClusterList( "Linkable Clusters Excluding Photons" ) ) + { + boolean isOk = false; + + try + { + isOk = m_LQChecker.accept( track , clus ); + } + catch( LinkDecisions.DecisionCannotBeMadeException e ) + { + isOk = false; + } + + if( isOk ) + { + seed = clus; + shower = m_showerContainer.createShower(m_chargedCalib, allSharedClusters, track, seed); + break; + } + } + */ +
//gamma shower.declareFlag( "isPrimary" , true );
@@ -231,108 +421,305 @@
System.out.println("ShowerBuilding: created "+showers.size()+" showers"); }
-// si = 0; -// for( Shower shower : showers ) -// { -// Set<Cluster> seeds = shower.getSeeds(); -// if(m_properties.getFlag("debug")){ -// System.out.println("ShowerBuilding: Shower "+si+" has "+seeds.size()+" seeds and "+shower.size()+" assigned clusters"); -// } -// ss = 0; -// for( Cluster seed : seeds ) -// { -// if(m_properties.getFlag("debug")){ -// System.out.println("ShowerBuilding: assiging clusters to seed "+ss+" which has "+seed.getCalorimeterHits().size()+" hits"); -// } -// assignLinksToCluster(seed, shower, m_showerContainer); -// ss++; -// } -// if(m_properties.getFlag("debug")){ -// System.out.println("ShowerBuilding: After assigning clusters to seeds, shower "+si+" has "+shower.size()+" assigned clusters"); -// } -// si++; -// } - - Set<Cluster> linkableClusters = new HashSet<Cluster>(); - linkableClusters.addAll(m_bookKeeper.getClusterList("Linkable Clusters Excluding Photons")); - Set<Cluster> linkedClusters = new HashSet<Cluster>(); - linkedClusters.addAll(m_showerContainer.getUsedClusters()); - Set<Cluster> unlinkedClusters = new HashSet<Cluster>(); - unlinkedClusters.addAll(linkableClusters); - unlinkedClusters.removeAll(linkedClusters); - Map<Cluster, List<ScoredLink>> potentialLinks = m_bookKeeper.getPotentialLinks(); - - for(Cluster seedCandidate : unlinkedClusters){ - - boolean foundLink = false; - for(Cluster base : linkableClusters){ - List<ScoredLink> linksForBase = potentialLinks.get(base); - if(linksForBase == null) continue; - for(ScoredLink link : linksForBase){ - if(link.counterpart(base) != seedCandidate) continue; - try{ - if(!m_linkDecision.accept(link)){ - continue; - } - if(!m_linkBreakDecision.accept(link)){ - break; - } - }catch(LinkDecisions.DecisionCannotBeMadeException e){continue;} - foundLink = true; - break;
+ si = 0; + + Collection<Cluster> mips = m_bookKeeper.getClusterList("Mips"); + Collection<Cluster> clumps = m_bookKeeper.getClusterList("Clumps"); + Collection<Cluster> leftoverHitClusters = m_bookKeeper.getClusterList( "Leftovers" ); + + Set<Shower> showers_ = new HashSet<Shower>(); + showers_.addAll( showers ); + + for( Shower shower : showers_ ) + { + Set<Cluster> seeds = shower.getSeeds(); + + Set<Cluster> seeds2 = new HashSet<Cluster>(); + seeds2.addAll( seeds ); // gammaphi + + Collection<Cluster> linkableClusters = m_bookKeeper.getClusterList( "Linkable Clusters Excluding Photons" ); + Set<Track> tracks2 = shower.getTracks(); + + boolean isSpineCase = false; + + /* + if( trk instanceof MultipleTrackTrack ) // FixMe!!! in case the direction of the tracks are so different. + { + + + int ii = 0; + for( Track subTrack : trk.getTracks() ) + { + HelixExtrapolationResult result = m_extrapolator.performExtrapolation( subTrack ); + if( result == null ) { System.out.println( "> + > + > Extrapolatin of the subTrack failed." ); continue; } + + result.extendToECALEndcapLayer( 0 ); + Hep3Vector vTemp = result.getInterceptPoint(); + Hep3Vector vTempDir = result.getTangent(); + + if( vTemp == null || vTempDir == null ) + { + result.extendToECALBarrelLayer( 0 ); + vTemp = result.getInterceptPoint(); + vTempDir = result.getTangent(); + } + + if( vTemp == null || vTempDir == null ) { System.out.println( "> + > + > Extrapolatin of the subTrack failed 2." ); continue; } + + positionOfTrack = VecOp.add( positionOfTrack , vTemp ); + directionOfTrack = VecOp.add( directionOfTrack , VecOp.unit( vTempDir ) ); + momentumOfTrack = VecOp.add( momentumOfTrack , new BasicHep3Vector( subTrack.getMomentum() ) ); + + HelixExtrapolationResult result2 = m_extrapolator.performExtrapolation( subTrack ); + listResult.add( result2 ); + + ii++; + } + + double scale = 1. / (double)ii; + positionOfTrack = VecOp.mult( scale , positionOfTrack ); + directionOfTrack = VecOp.unit( directionOfTrack ); + */ + + + + + if( tracks2.size() == 1 ) + { + isSpineCase = true; + + for( Track track : tracks2 ) + { + List<TrackerHit> listHits = track.getTrackerHits(); + if( listHits.size() == 0 ) + { + isSpineCase = false; + break; + } + + Hep3Vector positionOfTrack = null; + Hep3Vector directionOfTrack = null; + + HelixExtrapolationResult result = m_extrapolator.performExtrapolation( track ); + if( result == null ) + { + isSpineCase = false; + break; + } + + result.extendToECALEndcapLayer( 0 ); + positionOfTrack = result.getInterceptPoint(); + directionOfTrack = result.getTangent(); + + if( positionOfTrack == null || directionOfTrack == null ) + { + result.extendToECALBarrelLayer( 0 ); + positionOfTrack = result.getInterceptPoint(); + directionOfTrack = result.getTangent(); + } + + if( positionOfTrack == null || directionOfTrack == null ) + { + isSpineCase = false; + break; + } + + for( Cluster clus : linkableClusters ) + { + Hep3Vector positionOfClus = new BasicHep3Vector( clus.getPosition() ); + + Hep3Vector delta = VecOp.sub( positionOfClus , positionOfTrack ); + + double cosA = VecOp.dot( delta , directionOfTrack ) / ( delta.magnitude() * directionOfTrack.magnitude() ); + + double rr = delta.magnitude() * Math.sqrt( 1. - ( cosA * cosA ) ); + + if( rr < 3. ) + { + seeds2.add( clus ); + if( !shower.contains( clus ) ) m_showerContainer.addClusterToShower( shower , clus ); + } + } + } + } + + + + + if(m_properties.getFlag("debug")){ + System.out.println("ShowerBuilding: Shower "+si+" has "+seeds.size()+" seeds and "+shower.size()+" assigned clusters");
}
- if(foundLink) break; - } - if(foundLink) continue;
+ ss = 0; + + if( isSpineCase ) + { + for( Cluster seed : seeds2 ) + { + if(m_properties.getFlag("debug")){ + System.out.println("ShowerBuilding: assiging clusters to seed "+ss+" which has "+seed.getCalorimeterHits().size()+" hits"); + } + assignLinksToCluster(seed, shower, m_showerContainer); + ss++; + } + } + else + { + for( Cluster seed : seeds ) + { + if(m_properties.getFlag("debug")){ + System.out.println("ShowerBuilding: assiging clusters to seed "+ss+" which has "+seed.getCalorimeterHits().size()+" hits"); + } + assignLinksToCluster(seed, shower, m_showerContainer); + ss++; + } + } +
- Shower shhhh = m_showerContainer.createShower(m_neutralCalib, allSharedClusters, seedCandidate); - shhhh.declareFlag("isPrimary", false); - }
- while(unlinkedClusters.size()!=0){
- linkedClusters.addAll(m_showerContainer.getUsedClusters()); - unlinkedClusters.removeAll(linkedClusters);
+ // alpha + /* + Set<Track> tracks_ = shower.getTracks();
- ScoredLink bestLink = null; - for(Cluster base : linkedClusters){ - List<ScoredLink> linksForCluster = potentialLinks.get(base); - if(linksForCluster != null){ - for(ScoredLink link : linksForCluster){ - Cluster target = link.counterpart(base); - if(!unlinkedClusters.contains(target)) continue; - try{ - if(!m_linkDecision.accept(link)){ - continue;
+ double en_ = 100.; + + // for( Track track : tracks ) + { + en_ = shower.scalarMomentum() - shower.coreEnergy(); + if( en_ < 0. ) en_ = -1. * en_ ; + } + + if( en_ > 3. ) m_showerContainer.removeShower( shower ); + */ + ////////// + + boolean toSolve = false; + + double residual = ( shower.scalarMomentum() - shower.coreEnergy() ) / shower.estimatedEnergyUncertainty(); + if( residual > 5. ) + { + if( shower.getSeeds().size() == shower.getShowerComponents().size() ) toSolve = true; + } + + toSolve = false; + + if( toSolve ) + { + Set<Track> trks = shower.getTracks(); + + for( Track trk : trks ) + { + for( Cluster clus : m_bookKeeper.getClusterList( "Linkable Clusters Excluding Photons" ) ) + { + boolean isOk = false; + + try + { + isOk = m_LQChecker.accept( trk , clus ); + } + catch( LinkDecisions.DecisionCannotBeMadeException e ) + { + isOk = false; + } + + if( isOk ) + { + if( !shower.contains( clus ) ) + { + m_showerContainer.addClusterToShower( shower, clus ); + } + } + }
}
- if(!m_linkBreakDecision.accept(link)){ - break;
+ } + + + ////////// + /* + Set<Track> trks = shower.getTracks(); + + for( Track trk : trks ) + { + Cluster seed_ = shower.getSeed( trk ); + + if( leftoverHitClusters.contains( seed_ ) && clumps.contains( seed_ ) )// && seed_.getCalorimeterHits().size() >= 6 ) + { + for( Cluster clus : m_bookKeeper.getClusterList( "Linkable Clusters Excluding Photons" ) ) + { + boolean isOk = false; + + try + { + isOk = m_LQChecker.accept( trk , clus ); + } + catch( LinkDecisions.DecisionCannotBeMadeException e ) + { + isOk = false; + } + + if( isOk ) + { + if( !shower.contains( clus ) ) + { + m_showerContainer.addClusterToShower( shower, clus ); + } + } + }
}
- }catch(LinkDecisions.DecisionCannotBeMadeException e){continue;} - if(bestLink == null || link.score() > bestLink.score()){ - bestLink = link; - }
}
+ */ + + ////////// + + /* + Set<Track> trks = shower.getTracks(); + + for( Track trk : trks ) + { + for( Cluster clus : m_bookKeeper.getClusterList( "Linkable Clusters Excluding Photons" ) ) + { + boolean isOk = false; + + try + { + isOk = m_LQChecker.accept( trk , clus ); + } + catch( LinkDecisions.DecisionCannotBeMadeException e ) + { + isOk = false; + } + + if( isOk ) + { + if( !shower.contains( clus ) ) + { + m_showerContainer.addClusterToShower( shower, clus ); + } + } + } + } + */ + + ////////// + + + if(m_properties.getFlag("debug")){ + System.out.println("ShowerBuilding: After assigning clusters to seeds, shower "+si+" has "+shower.size()+" assigned clusters");
}
+ si++;
}
- if(bestLink != null){ - Cluster base = bestLink.getClusters()[0]; - Cluster target = bestLink.getClusters()[1]; - Set<Shower> baseShowers = m_showerContainer.getShowers(base); - for(Shower shower : baseShowers){ - m_showerContainer.addClusterToShower(shower, target); - } - // debugPrintLink(bestLink, baseShowers); - }else{ - break; - } - }
if(m_properties.getFlag("keepShowerContainersAtEachStep")) {
- m_bookKeeper.addShowerContainer("showers after first iteration", m_showerContainer.clone());
+ m_bookKeeper.addShowerContainer("showers after first iteration"+(useTrack?" using track":""), m_showerContainer.clone());
}
+ + MiscUtilities.useTrackDirection = false;
}
+ + + +
/** * second pass on charged shower building: * - a first pass on neutral shower building is done already at this step.
@@ -345,45 +732,43 @@
chargedClumpsCorrectionInEcal(); }
- //debugPrintShowerStatus("DebugFirstIteration"); -
/// decided to do a first pass on neutral hadrons here to solve charged/neutral ambiguities
- neutralHadronsFirstIteration(); - // perfectNeutralHadronsFirstIteration();
+ neutralHadronsFirstIteration(); + //perfectNeutralHadronsFirstIteration();
- // now come back and detect patological cases of E >> p - // these should be either combined with a nearby track or can be flagged as stealing neutral energy - // applyOverrides();
+ /// correction of the charged hadrons looking to the photons. + //chargedHadronsPhotonsCorrection();
-// debugPrintShowerStatus("DebugOverrides");
-// if(m_properties.getFlag("doPerfectSecondIteration")){ -// perfectSecondIteration(); -// }else{
+ // perfect second iteration + if( m_properties.getFlag( "doPerfectSecondIteration" ) ) + { + perfectSecondIteration(); + } + else + { + /// find primary neutrals + if( m_properties.getFlag( "makeShowerLikelihoodPDF" ) ) { + return; + } + flagPrimaryNeutrals(); + + /// resolve all overlaps... + // resolveOverlaps(); + + /// now look for detached charged energy and assign them to the correct track + if(m_properties.getFlag("makeShowerToShowerLikelihoodPDF")){ + return; + } + oldLinkSecondaryNeutrals(); + }
-// /// correction of the charged hadrons looking to the photons. -// //chargedHadronsPhotonsCorrection(); - - /// find primary neutrals - if( m_properties.getFlag( "makeShowerLikelihoodPDF" ) ) { - return; - } - flagPrimaryNeutrals(); - -// /// resolve all overlaps... -// // resolveOverlaps(); - -// /// now look for detached charged energy and assign them to the correct track - if(m_properties.getFlag("makeShowerToShowerLikelihoodPDF")){ - return; - } - oldLinkSecondaryNeutrals(); -// }
+ /// now check overlaps between neutral and charged showers and resolve + resolveChargedNeutralOverlaps();
-// /// now check overlaps between neutral and charged showers and resolve - // resolveChargedNeutralOverlaps();
+ // now do third iteration + thirdIteration();
- //debugPrintShowerStatus("DebugSecondIteration");
} protected void chargedClumpsCorrectionInEcal()
@@ -455,58 +840,58 @@
shower.declareFlag( "isPrimary" , false );
- assignLinksToCluster(seed, shower, m_showerContainer);
+ assignLinksToCluster(seed, shower, m_showerContainer, notYetLinkedClusters);
notYetLinkedClusters.removeAll(m_showerContainer.getUsedClusters()); }
- if( m_properties.getFlag( "keepShowerContainersAtEachStep" ) || - m_properties.getFlag("makeShowerLikelihoodPDF") ) { - m_bookKeeper.addShowerContainer( "showers after neutral showers first iterations" , m_showerContainer.clone() ); - }
+ if( m_properties.getFlag( "keepShowerContainersAtEachStep" ) || + m_properties.getFlag("makeShowerLikelihoodPDF") ) { + m_bookKeeper.addShowerContainer( "showers after neutral showers first iterations" , m_showerContainer.clone() ); + }
} protected void perfectNeutralHadronsFirstIteration() {
- List<SharedClusterGroup> allSharedClusters = m_bookKeeper.getAllSharedClusters(); - - /// seeds are clusters not yet used and close to the edge of the Ecal...
+ List<SharedClusterGroup> allSharedClusters = m_bookKeeper.getAllSharedClusters();
- /// First create a sorted list of such clusters were the order goes inside-out from the center of the detector... - List<Cluster> notYetLinkedClusters = new Vector<Cluster>(); - notYetLinkedClusters.addAll(m_bookKeeper.getClusterList("Linkable Clusters Excluding Photons")); - notYetLinkedClusters.removeAll(m_showerContainer.getUsedClusters()); - Collections.sort(notYetLinkedClusters, new PFAUtil.InsideOutNegativePoleCoparator());
+ /// seeds are clusters not yet used and close to the edge of the Ecal...
- /// Loop on the not yet used clusters: - // - take the closest one to the center of the detector and treat it as a seed - // - build a neutral shower for that seed - // - remove all used clusters from the not yet used clusters list - // - stop when the list is empty - while(notYetLinkedClusters.size() > 0){ - Cluster seed = notYetLinkedClusters.get(0); - if(seed == null){ - throw new AssertionError("Book keeping error"); - }
+ /// First create a sorted list of such clusters were the order goes inside-out from the center of the detector... + List<Cluster> notYetLinkedClusters = new Vector<Cluster>(); + notYetLinkedClusters.addAll(m_bookKeeper.getClusterList("Linkable Clusters Excluding Photons")); + notYetLinkedClusters.removeAll(m_showerContainer.getUsedClusters()); + Collections.sort(notYetLinkedClusters, new PFAUtil.InsideOutNegativePoleCoparator()); + + /// Loop on the not yet used clusters: + // - take the closest one to the center of the detector and treat it as a seed + // - build a neutral shower for that seed + // - remove all used clusters from the not yet used clusters list + // - stop when the list is empty + while(notYetLinkedClusters.size() > 0){ + Cluster seed = notYetLinkedClusters.get(0); + if(seed == null){ + throw new AssertionError("Book keeping error"); + }
- Shower shower = m_showerContainer.createShower(m_neutralCalib, allSharedClusters, seed);
+ Shower shower = m_showerContainer.createShower(m_neutralCalib, allSharedClusters, seed);
- shower.declareFlag( "isPrimary" , false );
+ shower.declareFlag( "isPrimary" , false );
- for(Cluster cluster : notYetLinkedClusters){ - if(cluster == seed) continue; - if(shower.contains(cluster)) continue; - try { - if(m_LQChecker.accept(cluster, seed)){ - m_showerContainer.addClusterToShower(shower, cluster); - } - }catch(LinkDecisions.DecisionCannotBeMadeException e){ - continue; - } - }
+ for(Cluster cluster : notYetLinkedClusters){ + if(cluster == seed) continue; + if(shower.contains(cluster)) continue; + try { + if(m_LQChecker.accept(cluster, seed)){ + m_showerContainer.addClusterToShower(shower, cluster); + } + }catch(LinkDecisions.DecisionCannotBeMadeException e){ + continue; + } + }
- notYetLinkedClusters.removeAll(m_showerContainer.getUsedClusters()); - }
+ notYetLinkedClusters.removeAll(m_showerContainer.getUsedClusters()); + }
} protected void chargedHadronsPhotonsCorrection()
@@ -598,259 +983,6 @@
} }
- protected void applyOverrides(){ - - Set<Shower> allShowers = new HashSet<Shower>(); - allShowers.addAll(m_showerContainer.getShowers()); - List<SharedClusterGroup> allSharedClusters = m_bookKeeper.getAllSharedClusters(); - - Set<Set<Shower>> showerGroups = m_showerContainer.getGroupsOfOverlappingShowers(); - Map<Shower, Set<Shower>> showerGroupMap = new HashMap<Shower, Set<Shower>>(); - for(Set<Shower> showerGroup : showerGroups){ - Set<Shower> copyShowerGroup = new HashSet<Shower>(); - copyShowerGroup.addAll(showerGroup); - for(Shower shower : copyShowerGroup){ - showerGroupMap.put(shower, copyShowerGroup); - } - } - - for(Shower shower : allShowers){ - - if(shower.isNeutral()) continue; - if(!m_showerContainer.contains(shower)) continue; - - double energy = shower.realEnergy(); - double momentum = shower.scalarMomentum(); - Hep3Vector vecMomentum = shower.momentum(); - double sigma = shower.estimatedEnergyUncertainty(); - - double residual = ( energy - momentum ) / sigma; - - double energySharedWithCharged = 0; - double energySharedWithNeutral = 0; - Set<Shower> showerGroup = showerGroupMap.get(shower); - if(showerGroup != null){ - Set<Cluster> allSharedClustersWithCharged = new HashSet<Cluster>(); - Set<Cluster> allSharedClustersWithNeutral = new HashSet<Cluster>(); - for(Shower sh : showerGroup){ - if(sh == shower) continue; - if(!m_showerContainer.contains(sh)) continue; - for(Cluster cl : sh.getShowerComponents()){ - if(shower.contains(cl)){ - if(sh.isNeutral()){ - allSharedClustersWithNeutral.add(cl); - }else{ - allSharedClustersWithCharged.add(cl); - } - } - } - } - energySharedWithCharged = PFAUtil.energy(allSharedClustersWithCharged, allSharedClusters, shower.getEnergyCalculator()); - energySharedWithNeutral = PFAUtil.energy(allSharedClustersWithNeutral, allSharedClusters, shower.getEnergyCalculator()); - } - - // apply overrides for large showers: - // - check if shower overlaps with another charged shower where if combined, the two showers have good E/P - // - else if shower overlaps with a neutral shower: should do something here. - // - else should do something else here - if(residual > 1.5){ -[truncated at 1000 lines; 1146 more skipped]
diff -u -r1.2 -r1.3 --- NonTrivialPFA.java 23 Oct 2011 09:50:31 -0000 1.2 +++ NonTrivialPFA.java 11 Apr 2012 15:49:36 -0000 1.3 @@ -11,7 +11,7 @@
import org.lcsim.digisim.DigiSimDriver; import org.lcsim.digisim.SimCalorimeterHitsDriver; import org.lcsim.recon.pfa.cheat.PerfectIdentifier;
-import org.lcsim.recon.pfa.identifier.*;
+import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.*;
import org.lcsim.recon.pfa.output.FlushReconstructedParticlesDriver; import org.lcsim.recon.cluster.mst.*; import org.lcsim.recon.cluster.mipfinder.*;
@@ -29,7 +29,7 @@
* a List<ReconstructedParticle>, written to the event as * PFAReconstructedParticles. *
- * @version $Id: NonTrivialPFA.java,v 1.2 2011/10/23 09:50:31 zaidan Exp $
+ * @version $Id: NonTrivialPFA.java,v 1.3 2012/04/11 15:49:36 zaidan Exp $
* @author Mat Charles <[log in to unmask]> */
@@ -341,8 +341,8 @@
{ LocalHelixExtrapolationTrackClusterMatcher extrapolate = new LocalHelixExtrapolationTrackClusterMatcher(new LocalHelixExtrapolator()); extrapolate.setCutSeparation(14.0); // about two cells
- org.lcsim.recon.pfa.identifier.SimpleTrackClusterMatcher simpleExtrapolate = new org.lcsim.recon.pfa.identifier.SimpleTrackClusterMatcher(14.0); - org.lcsim.recon.pfa.identifier.SimpleTrackClusterMatcher simpleCheatExtrapolate = new org.lcsim.recon.pfa.identifier.CheatHelixTrackClusterMatcher(14.0);
+ org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.SimpleTrackClusterMatcher simpleExtrapolate = new org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.SimpleTrackClusterMatcher(14.0); + org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.SimpleTrackClusterMatcher simpleCheatExtrapolate = new org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.CheatHelixTrackClusterMatcher(14.0);
CheatTrackClusterMatcher cheater = new CheatTrackClusterMatcher(mcListName); CheckSkeletonsForMultipleTracks separate = new CheckSkeletonsForMultipleTracks(evalWrapper, trackList, eventSkeletonClusters, eventSplitSkeletonClusters, eventMips, eventClumps, extrapolate); // LOCAL HELIX EXTRAPOLATION BASED ON SimTrackerHits //CheckSkeletonsForMultipleTracks separate = new CheckSkeletonsForMultipleTracks(evalWrapper, trackList, eventSkeletonClusters, eventSplitSkeletonClusters, eventMips, eventClumps, cheater); // CHEATING
@@ -846,8 +846,8 @@
MIPChargedParticleMaker hadIDmip = new MIPChargedParticleMaker(); LocalHelixExtrapolationTrackMIPClusterMatcher mipMatch = new LocalHelixExtrapolationTrackMIPClusterMatcher(new LocalHelixExtrapolator()); mipMatch.setDebug(debug);
- //org.lcsim.recon.pfa.identifier.SimpleTrackMIPClusterMatcher mipMatch = new org.lcsim.recon.pfa.identifier.SimpleTrackMIPClusterMatcher(); - //org.lcsim.recon.pfa.identifier.SimpleTrackMIPClusterMatcher mipMatch = new org.lcsim.recon.pfa.identifier.CheatHelixTrackMIPClusterMatcher();
+ //org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.SimpleTrackMIPClusterMatcher mipMatch = new org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.SimpleTrackMIPClusterMatcher(); + //org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.SimpleTrackMIPClusterMatcher mipMatch = new org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.CheatHelixTrackMIPClusterMatcher();
add(mipMatch); hadIDmip.setTrackMatcher(mipMatch); hadIDmip.setInputTrackList(trackList);
@@ -867,8 +867,8 @@
// Then try the clusters generically: SimpleChargedParticleMaker hadID = new SimpleChargedParticleMaker(); LocalHelixExtrapolationTrackClusterMatcher clusMatch = new LocalHelixExtrapolationTrackClusterMatcher(new LocalHelixExtrapolator());
- //org.lcsim.recon.pfa.identifier.SimpleTrackClusterMatcher clusMatch = new org.lcsim.recon.pfa.identifier.SimpleTrackClusterMatcher(); - //org.lcsim.recon.pfa.identifier.SimpleTrackClusterMatcher clusMatch = new org.lcsim.recon.pfa.identifier.CheatHelixTrackClusterMatcher();
+ //org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.SimpleTrackClusterMatcher clusMatch = new org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.SimpleTrackClusterMatcher(); + //org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.SimpleTrackClusterMatcher clusMatch = new org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.CheatHelixTrackClusterMatcher();
add(clusMatch); hadID.setTrackMatcher(clusMatch); hadID.setInputTrackList(prefix+"tracksMinusMipAssociations");
diff -u -r1.2 -r1.3 --- PFABookKeepingBroker.java 23 Oct 2011 09:50:31 -0000 1.2 +++ PFABookKeepingBroker.java 11 Apr 2012 15:49:36 -0000 1.3 @@ -5,7 +5,7 @@
import org.lcsim.event.*; import org.lcsim.recon.cluster.util.*; import org.lcsim.util.hitmap.*;
-import org.lcsim.recon.pfa.identifier.*;
+import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.*;
import org.lcsim.recon.util.CalorimeterInformation; import org.lcsim.geometry.Calorimeter.CalorimeterType; import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.structural.sharing.*;
diff -u -r1.1 -r1.2 --- PFAParticleMaker.java 23 Oct 2011 09:50:31 -0000 1.1 +++ PFAParticleMaker.java 11 Apr 2012 15:49:36 -0000 1.2 @@ -4,9 +4,9 @@
import hep.physics.vec.*; import hep.physics.particle.properties.*; import org.lcsim.event.*;
-import org.lcsim.recon.cluster.util.*; -import org.lcsim.recon.pfa.identifier.*;
import org.lcsim.event.base.*;
+import org.lcsim.recon.cluster.util.*; +import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.*;
import org.lcsim.util.decision.*; import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.structural.sharing.*; import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.structural.shower.*;
diff -u -r1.2 -r1.3 --- PFAUtil.java 23 Oct 2011 09:50:31 -0000 1.2 +++ PFAUtil.java 11 Apr 2012 15:49:36 -0000 1.3 @@ -7,7 +7,7 @@
import org.lcsim.recon.util.CalorimeterInformation; import org.lcsim.geometry.Calorimeter.CalorimeterType; import org.lcsim.geometry.*;
-import org.lcsim.recon.pfa.identifier.*;
+import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.*;
import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.structural.shower.*; import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.structural.sharing.*; import org.lcsim.event.base.*;
@@ -492,6 +492,7 @@
} static public double energy(Cluster mainCluster, List<SharedClusterGroup> listOfShares, ClusterEnergyCalculator calib) {
+ if(listOfShares == null) return energy(mainCluster, calib);
List<FuzzyCalorimeterHit> allFuzzyHits = new Vector<FuzzyCalorimeterHit>(); for (SharedClusterGroup share : listOfShares) { List<FuzzyCalorimeterHit> fuzzyHitsOfThisShare = findFuzzyHitsForCluster(mainCluster, share);
@@ -653,6 +654,7 @@
* Checks for duplicate hits in a collection of clusters */ static public void checkForDuplicateHitsInClusters(Collection<Cluster> clusters) {
+
Set<CalorimeterHit> allUsedHits = new HashSet<CalorimeterHit>(); List<CalorimeterHit> allUsedHitsList = new Vector<CalorimeterHit>(); for (Cluster clus : clusters) {
@@ -660,7 +662,7 @@
allUsedHits.add(hit); allUsedHitsList.add(hit); if (allUsedHits.size() != allUsedHitsList.size()) {
- throw new AssertionError("ERROR: Duplicate hit with ID "+hit.getCellID());
+ return; // throw new AssertionError("ERROR: Duplicate hit with ID "+hit.getCellID());
} } }
diff -u -r1.1 -r1.2 --- PhotonVetoDecision.java 23 Oct 2011 09:50:31 -0000 1.1 +++ PhotonVetoDecision.java 11 Apr 2012 15:49:36 -0000 1.2 @@ -5,7 +5,7 @@
import org.lcsim.event.*; import org.lcsim.recon.cluster.util.*; import org.lcsim.util.hitmap.*;
-import org.lcsim.recon.pfa.identifier.*;
+import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.*;
import org.lcsim.recon.util.CalorimeterInformation; import org.lcsim.geometry.Calorimeter.CalorimeterType; import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.structural.sharing.*;
diff -u -r1.1 -r1.2 --- PhotonVetoDriver.java 23 Oct 2011 09:50:31 -0000 1.1 +++ PhotonVetoDriver.java 11 Apr 2012 15:49:36 -0000 1.2 @@ -6,7 +6,7 @@
import org.lcsim.recon.cluster.util.*; import org.lcsim.util.hitmap.*; import org.lcsim.util.lcio.LCIOConstants;
-import org.lcsim.recon.pfa.identifier.*;
+import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.*;
import org.lcsim.recon.util.CalorimeterInformation; import org.lcsim.geometry.Calorimeter.CalorimeterType; import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.structural.sharing.*;
diff -u -r1.1 -r1.2 --- PreShowerMIPReassignmentAlgorithm.java 27 May 2011 12:01:12 -0000 1.1 +++ PreShowerMIPReassignmentAlgorithm.java 11 Apr 2012 15:49:36 -0000 1.2 @@ -6,7 +6,7 @@
import org.lcsim.event.*; import hep.physics.vec.*; import org.lcsim.geometry.Subdetector;
-import org.lcsim.recon.pfa.identifier.*;
+import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.*;
import org.lcsim.recon.cluster.util.BasicCluster; import org.lcsim.recon.util.CalorimeterInformation; import org.lcsim.geometry.Calorimeter.CalorimeterType;
diff -u -r1.2 -r1.3 --- ReclusterDTreeDriver.java 23 Oct 2011 09:50:31 -0000 1.2 +++ ReclusterDTreeDriver.java 11 Apr 2012 15:49:36 -0000 1.3 @@ -7,7 +7,7 @@
import org.lcsim.util.hitmap.*; import org.lcsim.event.*; import org.lcsim.recon.cluster.util.*;
-import org.lcsim.recon.pfa.identifier.*;
+import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.*;
import org.lcsim.event.base.*; import org.lcsim.contrib.uiowa.uiowapfa.recon.cluster.structural.likelihood.*; import org.lcsim.util.decision.*;
@@ -27,7 +27,7 @@
* in this package, which uses the implementation in * org.lcsim.recon.cluster.directedtree developed by NIU). *
- * @version $Id: ReclusterDTreeDriver.java,v 1.2 2011/10/23 09:50:31 zaidan Exp $
+ * @version $Id: ReclusterDTreeDriver.java,v 1.3 2012/04/11 15:49:36 zaidan Exp $
* @author Mat Charles <[log in to unmask]> */
@@ -68,6 +68,7 @@
protected DebugShowersDriver m_debugShowersCorrectionInEcal = null; protected DebugShowersDriver m_debugShowersNeutralFirstIteration = null; protected DebugShowersDriver m_debugShowersSecondaryNeutral = null;
+ protected DebugShowersDriver m_debugShowersThirdIteration = null;
protected DebugShowersDriver m_debugShowersNeutralChargedOverlaps = null; public void setDebugShowers(boolean doDebug){
@@ -79,6 +80,7 @@
add(m_debugShowersCorrectionInEcal); add(m_debugShowersNeutralFirstIteration); add(m_debugShowersSecondaryNeutral);
+ add(m_debugShowersThirdIteration);
add(m_debugShowersNeutralChargedOverlaps); } }
@@ -188,6 +190,8 @@
m_debugShowersNeutralFirstIteration.setOutputFileName( "ShowersAfterNeutralFirstIteration.aida" ); m_debugShowersSecondaryNeutral = new DebugShowersDriver( m_bookKeeper, m_extrapolator , mcList ); m_debugShowersSecondaryNeutral.setOutputFileName( "ShowersAfterSecondaryNeutralsLikelihood.aida" );
+ m_debugShowersThirdIteration = new DebugShowersDriver( m_bookKeeper, m_extrapolator , mcList ); + m_debugShowersThirdIteration.setOutputFileName( "ShowersAfterThirdIteration.aida" );
m_debugShowersNeutralChargedOverlaps = new DebugShowersDriver( m_bookKeeper, m_extrapolator , mcList ); m_debugShowersNeutralChargedOverlaps.setOutputFileName( "ShowersAfterNeutralChargedOverlapRemoval.aida" );
@@ -259,6 +263,7 @@
m_properties.declareCut("firstConeAlgorithm1" , 0.95 ); m_properties.declareCut("firstConeAlgorithm2" , 0.9 ); m_properties.declareKey("MCListName", m_mcList);
+ m_properties.declareCut("numberOfShowerBuildingIterations", 3);
m_properties.declareKey("EcalDigiHitMapName", "EcalDigiHitMap"); m_properties.declareKey("HcalDigiHitMapName", "HcalDigiHitMap"); m_properties.declareKey("MuonTrackClusterMapName", "MuonTrackClusterMap");
@@ -524,26 +529,32 @@
// } // ShowerContainer scNeutralFirstIteration = m_bookKeeper.getShowerContainer( "showers after flagging primary neutrals" ); // m_debugShowersNeutralFirstIteration.doAnalysis( scNeutralFirstIteration , linkableClusters , allSharedClusters );
-// ShowerContainer scSecondaryNeutral = m_bookKeeper.getShowerContainer( "charged showers after secondary neutrals likelihood" ); -// m_debugShowersSecondaryNeutral.doAnalysis( scSecondaryNeutral, linkableClusters , allSharedClusters );
+ ShowerContainer scSecondaryNeutral = m_bookKeeper.getShowerContainer( "charged showers after secondary neutrals likelihood" ); + m_debugShowersSecondaryNeutral.doAnalysis( scSecondaryNeutral, linkableClusters , allSharedClusters ); + ShowerContainer scThirdIteration = m_bookKeeper.getShowerContainer( "showers after third iterations" ); + m_debugShowersThirdIteration.doAnalysis( scThirdIteration, linkableClusters , allSharedClusters );
// ShowerContainer scNeutralChargedOverlaps = m_bookKeeper.getShowerContainer( "charged showers after resolving charged/neutral overlaps" ); // m_debugShowersNeutralChargedOverlaps.doAnalysis( scNeutralChargedOverlaps , linkableClusters , allSharedClusters ); }
- -// m_debugRegions.doAnalysis("showers after neutral showers first iterations", Math.PI/180, "regionsAfterFirstIteration_1degree"); -// m_debugRegions.doAnalysis("charged showers after secondary neutrals likelihood", Math.PI/180, "regionsAfterSecondIteration_1degree"); -// m_debugRegions.doAnalysis("showers after neutral showers first iterations", Math.PI/90, "regionsAfterFirstIteration_2degree"); -// m_debugRegions.doAnalysis("charged showers after secondary neutrals likelihood", Math.PI/90, "regionsAfterSecondIteration_2degree"); -// m_debugRegions.doAnalysis("showers after neutral showers first iterations", Math.PI/60, "regionsAfterFirstIteration_3degree"); -// m_debugRegions.doAnalysis("charged showers after secondary neutrals likelihood", Math.PI/60, "regionsAfterSecondIteration_3degree"); -// m_debugRegions.doAnalysis("showers after neutral showers first iterations", Math.PI/45, "regionsAfterFirstIteration_4degree"); -// m_debugRegions.doAnalysis("charged showers after secondary neutrals likelihood", Math.PI/45, "regionsAfterSecondIteration_4degree"); -// m_debugRegions.doAnalysis("showers after neutral showers first iterations", Math.PI/36, "regionsAfterFirstIteration_5degree"); -// m_debugRegions.doAnalysis("charged showers after secondary neutrals likelihood", Math.PI/36, "regionsAfterSecondIteration_5degree"); -// m_debugRegions.doAnalysis("showers after neutral showers first iterations", Math.PI/18, "regionsAfterFirstIteration_10degree"); -// m_debugRegions.doAnalysis("charged showers after secondary neutrals likelihood", Math.PI/18, "regionsAfterSecondIteration_10degree");
+ /* + m_debugRegions.doAnalysis("showers after neutral showers first iterations", Math.PI/180, "regionsAfterFirstIteration_1degree"); + m_debugRegions.doAnalysis("charged showers after secondary neutrals likelihood", Math.PI/180, "regionsAfterSecondIteration_1degree"); + m_debugRegions.doAnalysis("showers after neutral showers first iterations", Math.PI/90, "regionsAfterFirstIteration_2degree"); + m_debugRegions.doAnalysis("charged showers after secondary neutrals likelihood", Math.PI/90, "regionsAfterSecondIteration_2degree"); + m_debugRegions.doAnalysis("showers after neutral showers first iterations", Math.PI/60, "regionsAfterFirstIteration_3degree"); + m_debugRegions.doAnalysis("charged showers after secondary neutrals likelihood", Math.PI/60, "regionsAfterSecondIteration_3degree"); + m_debugRegions.doAnalysis("showers after neutral showers first iterations", Math.PI/45, "regionsAfterFirstIteration_4degree"); + m_debugRegions.doAnalysis("charged showers after secondary neutrals likelihood", Math.PI/45, "regionsAfterSecondIteration_4degree"); + // m_debugRegions.doAnalysis("charged showers after tiny neutrals", Math.PI/45, "regionsAfterTinyNeutrals_4degree"); + m_debugRegions.doAnalysis("showers after neutral showers first iterations", Math.PI/36, "regionsAfterFirstIteration_5degree"); + m_debugRegions.doAnalysis("charged showers after secondary neutrals likelihood", Math.PI/36, "regionsAfterSecondIteration_5degree"); +// m_debugRegions.doAnalysis("charged showers after tiny neutrals", Math.PI/36, "regionsAfterTinyNeutrals_5degree"); +// m_debugRegions.doAnalysis("charged showers after applying overrides", Math.PI/36, "regionsAfterApplyingOverrides_5degree"); + m_debugRegions.doAnalysis("showers after neutral showers first iterations", Math.PI/18, "regionsAfterFirstIteration_10degree"); + m_debugRegions.doAnalysis("charged showers after secondary neutrals likelihood", Math.PI/18, "regionsAfterSecondIteration_10degree");
// m_debugNeutrals.doAnalysis("All Showers", "allShowers");
+ */
// Outputs m_particleMaker.makeParticles();
diff -u -r1.2 -r1.3 --- ReclusterDriver.java 23 Oct 2011 09:50:31 -0000 1.2 +++ ReclusterDriver.java 11 Apr 2012 15:49:36 -0000 1.3 @@ -15,7 +15,7 @@
import org.lcsim.recon.cluster.mipfinder.*; import org.lcsim.recon.cluster.util.*; import org.lcsim.contrib.uiowa.uiowapfa.recon.cluster.clumpfinder.*;
-import org.lcsim.recon.pfa.identifier.*;
+import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.*;
import org.lcsim.mc.fast.tracking.ReconTrack; import org.lcsim.event.base.*; import hep.physics.particle.Particle;
@@ -42,7 +42,7 @@
* This version is superseeded by ReclusterDTreeDriver, * which derives from it. *
- * @version $Id: ReclusterDriver.java,v 1.2 2011/10/23 09:50:31 zaidan Exp $
+ * @version $Id: ReclusterDriver.java,v 1.3 2012/04/11 15:49:36 zaidan Exp $
* @author Mat Charles <[log in to unmask]> */
@@ -125,7 +125,7 @@
m_inputClumps = clumps; m_inputSplitSkeletonClusters = splitSkeletonClusters;
- initTrackMatch(new org.lcsim.recon.pfa.identifier.TrackHelixPlusHitExtrapolator());
+ initTrackMatch(new org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.TrackHelixPlusHitExtrapolator());
initCalibration(); if (m_debug) { initPlots(); }
diff -u -r1.2 -r1.3 --- RunAndWriteOutPFAFullTracking.java 23 Oct 2011 09:50:31 -0000 1.2 +++ RunAndWriteOutPFAFullTracking.java 11 Apr 2012 15:49:36 -0000 1.3 @@ -65,18 +65,18 @@
// add(new DebugSubClustersDriver("MCParticle")); // resolution + some histograms
- add(new MassPlots("FlushedDTreeReclusteredParticles", "output-write-reclustered-dtree.aida")); // Make some histograms and write them to a file
+ // add(new MassPlots("FlushedDTreeReclusteredParticles", "output-write-reclustered-dtree.aida")); // Make some histograms and write them to a file
m_eventSelection = new EventSelection(0, 0.95); m_eventCount = 0; }
- protected String m_linkLikelihoodPath = "structuralPFA/linkLikelihood.contrib.bin";
+ protected String m_linkLikelihoodPath = "structuralPFA/linkLikelihood.bin";
public void setLinkLikelihoodPath(String path) { m_linkLikelihoodPath = path; }
- protected String m_primaryShowerLikelihoodPath = "structuralPFA/likelihood.PrimaryShower.contrib.bin"; - public void setPrimaryShowerLikelihoodPath(String path) { m_primaryShowerLikelihoodPath = path; } - protected String m_showerToShowerLikelihoodPath = "structuralPFA/likelihood.ShowerToShower.contrib.bin";
+ protected String m_showerToShowerLikelihoodPath = "structuralPFA/likelihood.ShowerToShower.bin";
public void setShowerToShowerLikelihoodPath(String path) { m_showerToShowerLikelihoodPath = path; }
+ protected String m_primaryShowerLikelihoodPath = "structuralPFA/likelihood.PrimaryShower.bin"; + public void setPrimaryShowerLikelihoodPath(String path) { m_primaryShowerLikelihoodPath = path; }
protected int m_runMode = 0; // 0: analysis - 1: link training - 2: primary shower training - 3: shower to shower training public void setRunMode(int runMode){ m_runMode = runMode; }
@@ -93,9 +93,25 @@
} System.out.println("Start of event: "+m_eventCount);
- // if(m_eventSelection.pass(event)){ - super.process(event); - //}
+ if(m_eventSelection.pass(event)){ + + // List<Driver> subDrivers = super.drivers(); + // for (Driver driver : subDrivers){ + // if(driver instanceof MassPlots){ + // Boolean isEventOK = true;//(Boolean)event.get("isEventOK_regionsAfterSecondIteration_5degree"); + // if(isEventOK){ + // driver.doProcess(event); + // } + // }else{ + // driver.doProcess(event); + // } + // } + + super.process(event); + + + + }
System.out.println("End of event: "+m_eventCount); m_eventCount++; }
diff -u -r1.3 -r1.4 --- SetUpDTreeForReclustering.java 23 Oct 2011 10:07:47 -0000 1.3 +++ SetUpDTreeForReclustering.java 11 Apr 2012 15:49:36 -0000 1.4 @@ -14,17 +14,17 @@
import org.lcsim.recon.cluster.mipfinder.trackxtrap.*; import org.lcsim.recon.cluster.muonfinder.MuonFinderWrapper; import org.lcsim.recon.cluster.muonfinder.MuonFinderWrapper3;
-//ximport org.lcsim.recon.cluster.myclusterer.*;
+//import org.lcsim.recon.cluster.myclusterer.*;
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.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.recon.pfa.identifier.TrackToClusterSpecialCasesMapMaker;
+import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.AmbiguousTrackToClusterMapMaker; +import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.HelixExtrapolator; +import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.TrackToElectronMapMaker; +import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.TrackToGenericClusterMapMaker; +import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.TrackToMipClusterMapMaker; +import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.TrackToPreShowerMipMapMaker; +//import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.TrackToClusterSpecialCasesMapMaker;
import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.debug.DebugTrackToClusterSpecialCases; import org.lcsim.util.Driver; import org.lcsim.util.ListAddDriver;
@@ -80,7 +80,13 @@
{ init = true; CalorimeterInformation ci = CalorimeterInformation.instance();
-
+ + if(m_doBaseline) { + System.out.println(">>>>>>>>>>>>>>>>> running baseline setup..."); + }else{ + System.out.println(">>>>>>>>>>>>>>>>> running new setup..."); + } +
////// R.Z.: Filter out certain type of hits (e.g. neutrals) for testing... { boolean filterNeutralHadronHits = false; // should be FALSE for a real PFA !!!!!!!!
@@ -581,7 +587,6 @@
findCluster)); // now try to fix special cases of track/seed matching
- /*
DebugTrackToClusterSpecialCases specialMapMakerDebug = new DebugTrackToClusterSpecialCases(inputTrackList, "MCParticle", "EcalDigiHitMap",
@@ -609,8 +614,8 @@
specialMapMakerDebug.addTrackToClusterMap("MapMipClusterTracksToClusterSeeds"); specialMapMakerDebug.addTrackToClusterMap("MapGenClusterTracksToClusterSeeds"); specialMapMakerDebug.addTrackToClusterMap("MapAmbigClusterTracksToClusterSeeds");
- add(specialMapMakerDebug); - */
+ //add(specialMapMakerDebug); +
// now try to fix special cases of track/seed matching TrackToClusterSpecialCasesMapMaker specialMapMaker = new TrackToClusterSpecialCasesMapMaker(inputTrackList,
diff -u -r1.2 -r1.3 --- SetUpPFA.java 23 Oct 2011 09:50:31 -0000 1.2 +++ SetUpPFA.java 11 Apr 2012 15:49:36 -0000 1.3 @@ -5,7 +5,7 @@
import org.lcsim.event.*; import org.lcsim.event.util.*; import org.lcsim.util.decision.*;
-import org.lcsim.recon.pfa.identifier.*;
+import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.*;
import org.lcsim.recon.cluster.util.CalorimeterHitTimeCutDecision; import org.lcsim.recon.cluster.util.UpperSubLayerDecision; import org.lcsim.recon.util.CalorimeterInformation;
@@ -17,7 +17,7 @@
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();
+ HelixExtrapolator findCluster = new org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.TrackHelixPlusHitExtrapolator();
ReclusterDTreeDriver reclusTree = null; public void setFilterInputTrack(String x){ fil.setInputList(x); }
@@ -37,7 +37,7 @@
private boolean useNewInitialMipFinding = false; public void setUseNewInitialMipFinding(boolean x){useNewInitialMipFinding = x;}
- protected String m_linkLikelihoodPath = "structuralPFA/linkLikelihood.bin";
+ protected String m_linkLikelihoodPath = "structuralPFA/likelihood.bin";
public void setLinkLikelihoodPath(String path) { m_linkLikelihoodPath = path; } protected String m_showerToShowerLikelihoodPath = "structuralPFA/showerToShowerLikelihood.bin"; public void setShowerToShowerLikelihoodPath(String path) { m_showerToShowerLikelihoodPath = path; }
@@ -45,6 +45,15 @@
public void setPrimaryShowerLikelihoodPath(String path) { m_primaryShowerLikelihoodPath = path; } protected int m_runMode = 0; // 0: analysis - 1: link training - 2: primary shower training - 3: shower to shower training public void setRunMode(int runMode){ m_runMode = runMode; }
+ protected boolean m_doBaselinePFA = false; + public void doBaseline(boolean baseline) { m_doBaselinePFA = baseline; } + protected int m_nIter = 3; + public void numberOfIterations(int n) { m_nIter = n; } + + protected String trackList; + protected String mcList; + public void setTrackList(String tracks) { trackList = tracks; } + public void setMcList(String mc) { mcList = mc; }
public SetUpPFA(){ this("Tracks");
@@ -52,9 +61,6 @@
public SetUpPFA(String trackList) { this(trackList, "ReconFSParticles"); }
- - String trackList; - String mcList;
public SetUpPFA(String _trackList, String _mcList){ trackList = _trackList; mcList = _mcList;
@@ -67,6 +73,12 @@
{ init = true;
+ if(m_doBaselinePFA) { + System.out.println(">>>>>>>>>>>>>>>>> running baseline PFA"); + }else{ + System.out.println(">>>>>>>>>>>>>>>>> running new PFA"); + } +
// Filter tracks, removing those with unphysical energy {
@@ -113,7 +125,7 @@
allHitLists.add("CorrMuonBarrelDigiHits"); mstHitLists.add(ci.getDigiCollectionName(CalorimeterType.MUON_ENDCAP)); SetUpDTreeForReclustering setup = new SetUpDTreeForReclustering("FilteredTrackList", allHitLists, recoHitLists, mstHitLists, findCluster);
- //setup.doBaseline(true);
+ setup.doBaseline(m_doBaselinePFA || m_runMode == 1);
//setup.setSafeMode(true); //setup.cheatOnPhotons(true); //setup.doCheatClustering(true);
@@ -138,25 +150,32 @@
reclusTree.addInputLeftoverHits("LeftoverHitsInsideTreesECAL"); reclusTree.addInputLeftoverHits("LeftoverHitsInsideTreesHCAL"); reclusTree.addInputLeftoverHits("LeftoverHitsInsideTreesMCAL");
- //reclusTree.addTrackToClusterMap("MapPreShowerMipTracksToClusterSeeds"); - //reclusTree.addTrackToClusterMap("MapMipClusterTracksToClusterSeeds"); - //reclusTree.addTrackToClusterMap("MapGenClusterTracksToClusterSeeds"); - //reclusTree.addTrackToClusterMap("MapAmbigClusterTracksToClusterSeeds"); - reclusTree.addTrackToClusterMap("TracksMatchedToClusters");
+ if(m_doBaselinePFA || m_runMode == 1) { + reclusTree.addTrackToClusterMap("MapPreShowerMipTracksToClusterSeeds"); + reclusTree.addTrackToClusterMap("MapMipClusterTracksToClusterSeeds"); + reclusTree.addTrackToClusterMap("MapGenClusterTracksToClusterSeeds"); + reclusTree.addTrackToClusterMap("MapAmbigClusterTracksToClusterSeeds"); + } else { + reclusTree.addTrackToClusterMap("TracksMatchedToClusters"); + }
//reclusTree.getProperties().setFlag("debug", true); // default false //reclusTree.getProperties().setFlag("safeMode", true); // default false
- //reclusTree.getProperties().setFlag("doBaselinePFA", true); // default false
+ reclusTree.getProperties().setFlag("doBaselinePFA", true); // default false
//reclusTree.getProperties().setFlag("doBaselineShowerBuilding", true); // default false //reclusTree.getProperties().setFlag("doFirstConeAlgorithm", true); // default false
+ //reclusTree.getProperties().setCut("numberOfShowerBuildingIterations", (double)m_nIter); // default 3
//reclusTree.getProperties().setFlag("doCheatScoring", true); // default false //reclusTree.getProperties().setFlag("doPerfectShowerBuilding", true); // default false //reclusTree.getProperties().setFlag("doPerfectSecondIteration", true); // default false //reclusTree.getProperties().setCut( "firstConeAlgorithm1" , 0.95 ); // default 0.95 //reclusTree.getProperties().setCut( "firstConeAlgorithm2" , 0.9 ); // default 0.9
- reclusTree.getProperties().setCut("scoreCut", 0.9); // default 0.7
+ // if(!m_doBaselinePFA){ + // reclusTree.getProperties().setCut("scoreCut", 0.99); // default 0.7 + // }
//reclusTree.getProperties().setFlag("doDebugPhotons", true); // default false //reclusTree.getProperties().setFlag("doDebugParticles", true); // default false
- // reclusTree.setDebugLinks(true);
+ //reclusTree.setDebugLinks(true); + //reclusTree.setDebugShowers(true);
reclusTree.getProperties().setKey("LikelihoodPath", m_linkLikelihoodPath); reclusTree.getProperties().setKey("showerLikelihoodPath", m_primaryShowerLikelihoodPath); reclusTree.getProperties().setKey("showerToShowerLikelihoodPath", m_showerToShowerLikelihoodPath);
diff -u -r1.1 -r1.2 --- TrackToClusterCosAngle.java 23 Oct 2011 09:50:31 -0000 1.1 +++ TrackToClusterCosAngle.java 11 Apr 2012 15:49:36 -0000 1.2 @@ -4,7 +4,7 @@
import hep.physics.vec.*; import org.lcsim.contrib.uiowa.uiowapfa.recon.cluster.structural.likelihood.*; import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.structural.*;
-import org.lcsim.recon.pfa.identifier.*;
+import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.*;
public class TrackToClusterCosAngle extends TrackToClusterLikelihoodQuantity {
diff -u -r1.1 -r1.2 --- TrackToClusterDistance.java 23 Oct 2011 09:50:31 -0000 1.1 +++ TrackToClusterDistance.java 11 Apr 2012 15:49:36 -0000 1.2 @@ -4,7 +4,7 @@
import hep.physics.vec.*; import org.lcsim.contrib.uiowa.uiowapfa.recon.cluster.structural.likelihood.*; import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.structural.*;
-import org.lcsim.recon.pfa.identifier.*;
+import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.*;
public class TrackToClusterDistance extends TrackToClusterLikelihoodQuantity {
diff -u -r1.1 -r1.2 --- TrackToClusterForce.java 23 Oct 2011 09:50:31 -0000 1.1 +++ TrackToClusterForce.java 11 Apr 2012 15:49:36 -0000 1.2 @@ -4,7 +4,7 @@
import hep.physics.vec.*; import org.lcsim.contrib.uiowa.uiowapfa.recon.cluster.structural.likelihood.*; import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.structural.*;
-import org.lcsim.recon.pfa.identifier.*;
+import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.*;
public class TrackToClusterForce extends TrackToClusterLikelihoodQuantity {
diff -u -r1.1 -r1.2 --- TrackToClusterLikelihoodQuantity.java 23 Oct 2011 09:50:31 -0000 1.1 +++ TrackToClusterLikelihoodQuantity.java 11 Apr 2012 15:49:36 -0000 1.2 @@ -2,7 +2,7 @@
import org.lcsim.event.*; import org.lcsim.contrib.uiowa.uiowapfa.recon.cluster.structural.likelihood.*;
-import org.lcsim.recon.pfa.identifier.HelixExtrapolator;
+import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.HelixExtrapolator;
/** * Extends the StructuralLikelihoodQuantity and foces arguments of type Shower
diff -u -r1.3 -r1.4 --- TrackToClusterSpecialCasesMapMaker.java 23 Oct 2011 10:28:04 -0000 1.3 +++ TrackToClusterSpecialCasesMapMaker.java 11 Apr 2012 15:49:36 -0000 1.4 @@ -9,7 +9,7 @@
import org.lcsim.recon.cluster.util.*; import org.lcsim.recon.cluster.mipfinder.*; import org.lcsim.contrib.uiowa.uiowapfa.recon.cluster.structural.likelihood.*;
-import org.lcsim.recon.pfa.identifier.*;
+import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.*;
import org.lcsim.geometry.Calorimeter.CalorimeterType; import org.lcsim.geometry.*;
@@ -36,14 +36,11 @@
boolean m_init;
- String m_inputTrackListNameThis; -
public TrackToClusterSpecialCasesMapMaker(String inputTrackList, String outputMap, String outputUnmatchedTrackList, HelixExtrapolator extrapolator) { super(inputTrackList, outputMap, outputUnmatchedTrackList);
- m_inputTrackListNameThis = inputTrackList;
m_trackToClusterMapNames = new Vector<String>(); m_mipListNames = new Vector<String>(); m_clumpListNames = new Vector<String>();
@@ -53,7 +50,7 @@
m_extrapolator = extrapolator;
- m_eval = new LikelihoodEvaluatorWrapper("structuralPFA/linkLikelihood.contrib.bin");
+ m_eval = new LikelihoodEvaluatorWrapper("structuralPFA/likelihood.bin");
m_properties = new PropertyContainer(); m_properties.declareFlag("attachMipsFromDTree", false);
@@ -119,7 +116,7 @@
if(m_properties.getFlag("considerMipsInLinkableClusters")) linkableClustersForExtrapolation.addAll(mips); linkableClustersForExtrapolation.addAll(clumps); linkableClustersForExtrapolation.addAll(blocks);
- trackList = event.get(Track.class, m_inputTrackListNameThis);
+ trackList = event.get(Track.class, m_inputTrackListName);
// input track-seed matching trackToClusterMap = new HashMap<Track,Cluster>();
diff -u -r1.2 -r1.3 --- ClusterSharingAlgorithmWrapper.java 23 Oct 2011 09:50:32 -0000 1.2 +++ ClusterSharingAlgorithmWrapper.java 11 Apr 2012 15:49:37 -0000 1.3 @@ -107,8 +107,6 @@
maxDistanceForProximityClustersMCAL = 99999.9; // effectively no cut-off }
- boolean excludePhotonsFromCone = true; -
List<SharedClusterGroup> allSharedClusters = m_bookKeeper.getAllSharedClusters(); // Small clusters {
diff -N ShowerBranch.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ShowerBranch.java 11 Apr 2012 15:49:37 -0000 1.1 @@ -0,0 +1,92 @@
+package org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.structural.shower; + +import java.util.*; +import hep.physics.vec.*; +import org.lcsim.event.*; + +public class ShowerBranch +{ + protected List<Cluster> m_listClusters = new Vector<Cluster>(); + protected Cluster m_lastAddedCluster; + protected Hep3Vector m_branchPoint = null; + protected Hep3Vector m_direction = null; + protected Hep3Vector m_position = null; + protected int m_id; + static protected int ms_instanceCount = 0; + + protected ShowerWithBranches m_mother = null; + + public ShowerBranch() + { + this(new BasicHep3Vector(0,0,0)); + } + + public ShowerBranch(Hep3Vector branchPoint) + { + m_branchPoint = branchPoint; + ms_instanceCount++; + m_id = ms_instanceCount; + } + + public void addCluster( Cluster clus ) + { + m_listClusters.add( clus ); + m_lastAddedCluster = clus; + + m_position = new BasicHep3Vector( clus.getPosition() ); + + Hep3Vector vSum = new BasicHep3Vector( 0. , 0. , 0. ); + for( int i = 0 ; i < m_listClusters.size() ; i++ ) + { + Hep3Vector v = null; + if( i == 0 ) + { + v = VecOp.sub( new BasicHep3Vector( m_listClusters.get(i).getPosition() ) , m_branchPoint ); + v = VecOp.unit( v ); + } + else + { + v = VecOp.sub( new BasicHep3Vector( m_listClusters.get(i).getPosition() ) , new BasicHep3Vector( m_listClusters.get(i-1).getPosition() ) ); + v = VecOp.unit( v ); + } + vSum = VecOp.add( vSum , v ); + } + m_direction = VecOp.mult( 1. / (double)m_listClusters.size() , vSum ); + } + + public Cluster getLastAddedCluster() + { + return m_lastAddedCluster; + } + + public List<Cluster> getClusters() + { + return m_listClusters; + } + + public int getSize() + { + return m_listClusters.size(); + } + + public double getEnergy() + { + double e = 0.; + for( Cluster clus : m_listClusters ) e += clus.getEnergy(); + return e; + } + + public Hep3Vector getDirection() { return m_direction; } + + public Hep3Vector getPosition() { return m_position; } + + public double getMomentum() { return m_mother.getMomentum(); } + + public boolean isCharged() { return m_mother.isCharged(); } + + public int getId() { return m_id; } + + public ShowerWithBranches getMother(){ return m_mother; } + public void setMother(ShowerWithBranches mother){ m_mother = mother; } + +}
diff -N ShowerWithBranches.java --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ ShowerWithBranches.java 11 Apr 2012 15:49:37 -0000 1.1 @@ -0,0 +1,112 @@
+package org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.structural.shower; + +import java.util.*; +import hep.physics.vec.*; +import hep.physics.particle.properties.*; +import org.lcsim.event.*; +import org.lcsim.event.base.*; +import org.lcsim.recon.cluster.util.*; +import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.structural.sharing.*; +import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.structural.*; + +public class ShowerWithBranches +{ + protected List<ShowerBranch> m_branches = null; + static protected int m_idCount = 0; + protected int m_id; + protected Set<Track> m_tracks; + + List<SharedClusterGroup> m_sharedClusters = null; + ClusterEnergyCalculator m_calib; + + public ShowerWithBranches(ClusterEnergyCalculator calib) + { + m_tracks = new HashSet<Track>(); + m_calib = calib; + m_branches = new Vector<ShowerBranch>(); + m_idCount ++; + m_id = m_idCount; + } + + public List<SharedClusterGroup> getSharedClusters() { return m_sharedClusters; } + public void setSharedClusters(List<SharedClusterGroup> sharedClusters) { m_sharedClusters = sharedClusters; } + + public Hep3Vector getVecMomentum() { + Hep3Vector sumVectMomentum = new BasicHep3Vector( 0. , 0. , 0. ); + for(Track track : m_tracks) { + sumVectMomentum = VecOp.add( sumVectMomentum , new BasicHep3Vector(track.getMomentum()) ); + } + return sumVectMomentum; + } + + public double getMomentum() { + return getVecMomentum().magnitude(); + } + + public double getEnergyUncertainty() { + // prep: pion mass + int pdg_pi = 211; + ParticleType type_pi = ParticlePropertyManager.getParticlePropertyProvider().get(pdg_pi); + BaseParticleID pid_pi = new BaseParticleID(type_pi); + double mass_pi = type_pi.getMass(); + + double uncertainty = 0; + for(Track track : m_tracks) { + double momentum = (new BasicHep3Vector(track.getMomentum())).magnitude(); + double energy = Math.sqrt(momentum*momentum + mass_pi*mass_pi); + double sigma = 0.7 * Math.sqrt(energy); + if ( energy < 1.0) { + sigma = 0.7; + } + uncertainty += sigma*sigma; + } + + return Math.sqrt(uncertainty); + } + + public double getEnergy() { + double e = 0; + for(ShowerBranch branch : m_branches) { + e += branch.getEnergy(); + } + return e; + } + + public double getRealEnergy() { + + List<Cluster> clusterList = new Vector<Cluster>(); + for( ShowerBranch showerBranch : m_branches ) { + clusterList.addAll( showerBranch.getClusters() ); + } + + return PFAUtil.energy(clusterList, m_sharedClusters, m_calib); + } + + public boolean isCharged( ) { return m_tracks.size() > 0; } + + public Set<Track> getTracks() { return m_tracks; } + public void addTrack(Track track) { m_tracks.add(track); } + + public List<ShowerBranch> getBranches(){ return m_branches; } + public void addBranch(ShowerBranch branch){ + m_branches.add(branch); + branch.setMother(this); + } + + public int getId() { return m_id; } + + protected boolean m_isSpecial = false; + public boolean isSpecial(){ return m_isSpecial; } + public void setSpecial(boolean s){ m_isSpecial = s; } + + public Cluster getCluster() + { + BasicCluster cluster = new BasicCluster(); + + for( ShowerBranch showerBranch : m_branches ) + for( Cluster clus : showerBranch.getClusters() ) + cluster.addCluster(clus); + + return cluster; + } +}
diff -u -r1.2 -r1.3 --- Shower.java 23 Oct 2011 09:50:32 -0000 1.2 +++ Shower.java 11 Apr 2012 15:49:37 -0000 1.3 @@ -6,7 +6,7 @@
import org.lcsim.recon.cluster.util.*; import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.structural.sharing.*; import org.lcsim.event.base.*;
-import org.lcsim.recon.pfa.identifier.*;
+import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.identifier.*;
import org.lcsim.util.swim.*; import org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.structural.*;
diff -u -r1.2 -r1.3 --- ShowerContainer.java 23 Oct 2011 09:50:32 -0000 1.2 +++ ShowerContainer.java 11 Apr 2012 15:49:37 -0000 1.3 @@ -161,8 +161,10 @@
} public Shower createShower(ClusterEnergyCalculator calib, List<SharedClusterGroup> listOfShares, Set<Track> tracks, Map<Track, Cluster> seedMap){
- if(m_trackToShowerMap.get(tracks) != null){ - throw new AssertionError("Book keeping error: track already assigned to shower");
+ for(Track track : tracks){ + if(m_trackToShowerMap.get(track) != null){ + //throw new AssertionError("Book keeping error: track already assigned to shower"); + }
} Shower shower = ShowerFactory.createShower(calib, listOfShares, tracks, seedMap); Set<Cluster> seeds = shower.getSeeds();
diff -N compile.sh --- compile.sh 27 May 2011 12:01:14 -0000 1.1 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,11 +0,0 @@
-#!/bin/bash -f - -codePath=~/pfa/lcsim # <-- change this path according to the local setup - -curdir=$PWD - -cd $codePath/lcsim-contrib - -mvn $1 -DskipTests=true && cd $codePath/lcsim-contrib/src/main/java/org/lcsim && tar -czf $HOME/.JAS3/extensions/snapshot.tar.gz contrib; cd -; - -cd $curdir
diff -N computeCorrelations.sh --- computeCorrelations.sh 27 May 2011 12:01:14 -0000 1.1 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,3 +0,0 @@
-#!/bin/bash - -./macro-run.sh org.lcsim.contrib.uiowa.uiowapfa.macros.ComputeCorrelations $@
diff -N computeEfficiencyVsRejection.sh --- computeEfficiencyVsRejection.sh 27 May 2011 12:01:14 -0000 1.1 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,3 +0,0 @@
-#!/bin/bash - -./macro-run.sh org.lcsim.contrib.uiowa.uiowapfa.macros.EfficiencyVsRejection $@
diff -N exportCLASSPATH.sh --- exportCLASSPATH.sh 27 May 2011 12:01:14 -0000 1.1 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,9 +0,0 @@
- -if [ ! -e .jarlist ] ; then - echo "ERROR: .jarlist not found: make sure you have run either the java-init.sh or the java-init-cache.sh in your working directory" - exit 1 -fi - -export CLASSPATH="." -for f in $(cat .jarlist) ; { export CLASSPATH="$CLASSPATH:$f"; } -
diff -N importCode.csh --- importCode.csh 27 May 2011 13:09:20 -0000 1.1 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,186 +0,0 @@
-#!/bin/csh -f - -#### This part constitute actually a hard-coded input to this script -set packages = "" -set packages = "${packages} recon.cluster.clumpfinder" -set packages = "${packages} recon.cluster.clumpfinder.kmean" -set packages = "${packages} recon.cluster.structural" -set packages = "${packages} recon.cluster.structural.likelihood" -set packages = "${packages} recon.pfa.structural" -set packages = "${packages} recon.pfa.structural.sharing" -set packages = "${packages} recon.pfa.structural.shower" - -set mainDir = "lcsim/src/org/lcsim" -set contribDir = "lcsim-contrib/src/main/java/org/lcsim/contrib/uiowa/uiowapfa" -set mainPrefix = "org.lcsim" -set contribPrefix = "org.lcsim.contrib.uiowa.uiowapfa" -############################################################ - - - -alias printInfo 'if(${beVerbose} == true) echo' - -set label = "main" -goto ${label} - -displayHelp: - if( ${copyMode} == "undefined" ) then - set src = "<path>/<relative path to source>" - set dst = "<path>/<relative path to destination>" - set srcPrefix = "<source root package>" - set dstPrefix = "<destination root package>" - endif - echo "" - echo " This script will import uiowa PFA code from the location:" - echo " ${src}" - echo " to the location:" - echo " ${dst}" - echo "" - if( ${beVerbose} == true ) then - echo " The following packages will be immported:" - foreach package (${packages}) - echo " ${srcPrefix}.${package} into ${dstPrefix}.${package}" - end - echo "" - echo " All *.java files in the following locations, if they exist, will be overwritten" - foreach package (${packages}) - set packageLocation = `echo ${dst}/${package} | sed "s,\.,/,g"` - echo " ${packageLocation}" - end - echo "" - echo " Package declarations and import commands will be fixed in the imported *java files." - echo "" - endif - if( ${copyMode} == undefined ) then - echo " where in import mode:" - echo " <relative path to source> = ${mainDir}" - echo " <relative path to destination> = ${contribDir}" - printInfo " <source root package> = ${mainPrefix}" - printInfo " <destination root package> = ${contribPrefix}" - echo " and in export mode:" - echo " <relative path to source> = ${contribDir}" - echo " <relative path to destination> = ${mainDir}" - printInfo " <source root package> = ${contribPrefix}" - printInfo " <destination root package> = ${mainPrefix}" - echo "" - endif - goto ${label} - -displayUsage: - echo "" - echo " Usage: ${script} [-i,--import|-e,--export] [-v,--verbose] [-h,--help] <path>" - echo " Options are:" - echo " -h, --help: print help message and exit" - echo " -v, --verbose: execute in verbose mode" - echo " -e, --export: export from contrib to main area" - echo " -i, --import: import from main area to contrib" - echo "" - goto ${label} - -# Main -main: - -set script = $0 -set localPath = "path" -set copyMode = undefined -set beVerbose = false - -foreach arg ($argv) - if( ${arg} == "--help" || ${arg} == "-h" ) then - set label = helping - goto displayUsage - helping: - set copyMode = undefined - set beVerbose = true - set label = endOfScript - goto displayHelp - else if( ${arg} == "--verbose" || ${arg} == "-v" ) then - set beVerbose = true - else if( ${arg} == "--export" || ${arg} == "-e" ) then - set copyMode = exporting - else if( ${arg} == "--import" || ${arg} == "-i" ) then - set copyMode = importing - else if( ${localPath} == "path" ) then - set localPath = ${arg} - else - echo "agument $arg was ignored: path = $localPath" - endif -end - -if( ${copyMode} == exporting ) then - set src = "${localPath}/${contribDir}" - set dst = "${localPath}/${mainDir}" - set srcPrefix = ${contribPrefix} - set dstPrefix = ${mainPrefix} -else if( ${copyMode} == importing ) then - set src = "${localPath}/${mainDir}" - set dst = "${localPath}/${contribDir}" - set srcPrefix = ${mainPrefix} - set dstPrefix = ${contribPrefix} -else - echo "You must run in either import or export mode" - set label = endOfScript - goto displayUsage -endif - -if (${localPath} == "path") then - echo "Not enough arguments" - set label = endOfScript - goto displayUsage -endif - -set label = promptForProceed -goto displayHelp - -promptForProceed: - -echo "Do you wish to proceed with this operation? [y/N]" -set resp = $< -set resp = `echo ${resp} | tr '[A-Z]' '[a-z]'` -if(${resp} != "y") then - echo "operation aborted by user..." - goto endOfScript -endif - -if (! -d ${src}) then - echo "the code was not found at the source:" - echo " ${src}: no such directory" - goto endOfScript -endif - -foreach package ($packages) - set srcPackage = ${srcPrefix}.${package} - set dstPackage = ${dstPrefix}.${package} - set packageSrcDir = `echo ${src}/${package} | sed "s,\.,/,g"` - set packageDstDir = `echo ${dst}/${package} | sed "s,\.,/,g"` - echo "Working on package: ${srcPackage}" - printInfo " destination package: ${dstPackage}" - if(! -d ${packageSrcDir}) then - echo "source code not found: ${packageSrcDir} no such directory" - goto endScript - endif - printInfo " source code is at: ${packageSrcDir}" - printInfo " destination code is at: ${packageDstDir}" - if(-d ${packageDstDir}) then - printInfo " destination code already exist: removing *.java files from destination" - rm -f ${packageDstDir}/*.java - else - printInfo " destination code does not exist: creating it" - mkdir -p ${packageDstDir} - endif - printInfo " now copying *.java files from source to destination" - cp ${packageSrcDir}/*.java ${packageDstDir} - printInfo " now fixing package declarations and import commands" - foreach p (${packages}) - set srcp = ${srcPrefix}.${p} - set dstp = ${dstPrefix}.${p} - echo " replacing ${srcp} by ${dstp}" - foreach file (${packageDstDir}/*.java) - cat ${file} | sed "s,${srcp},${dstp},g" > tmp - mv tmp ${file} - end - end -end - -endOfScript: - exit
diff -N java-init-cache.sh --- java-init-cache.sh 27 May 2011 12:01:14 -0000 1.1 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,26 +0,0 @@
-#! /bin/sh - -# For a linux machine at SLAC: -SOURCEDIR_JAS3=/afs/slac.stanford.edu/package/jas/release/jas3/jas3-0.8.3 - -if [ ! -d "$SOURCEDIR_JAS3" ]; then - echo "WARNING: jas3 not found at $SOURCEDIR_JAS3" -fi - -# For a unix machine in general: -SOURCEDIR_HOME=$HOME/.JAS3 - -if [ ! -d "$SOURCEDIR_HOME" ]; then - echo "WARNING: .JAS3 not found at $SOURCEDIR_HOME" -fi - -rm -f .jarlist -touch .jarlist -find $SOURCEDIR_JAS3 -name "*.jar" -follow >> .jarlist -find $SOURCEDIR_HOME -name "*.jar" -follow | grep -v "extensions" >> .jarlist - -rm -rf .workdir -mkdir -p .workdir -cp $HOME/.JAS3/extensions/*jar .workdir -cp $HOME/.JAS3/extensions/snapshot.tar.gz .workdir -find .workdir -name "*.jar" >> .jarlist
diff -N java-init.sh --- java-init.sh 27 May 2011 12:01:14 -0000 1.1 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,21 +0,0 @@
-#! /bin/sh - -# For a linux machine at SLAC: -SOURCEDIR_JAS3=/afs/slac.stanford.edu/package/jas/release/jas3/jas3-0.8.3 - -if [ ! -d "$SOURCEDIR_JAS3" ]; then - echo "WARNING: jas3 not found at $SOURCEDIR_JAS3" -fi - -# For a unix machine in general: -SOURCEDIR_HOME=$HOME/.JAS3 - -if [ ! -d "$SOURCEDIR_HOME" ]; then - echo "WARNING: .JAS3 not found at $SOURCEDIR_HOME" -fi - -rm -f .jarlist -touch .jarlist -find $SOURCEDIR_JAS3 -name "*.jar" -follow >> .jarlist -find $SOURCEDIR_HOME -name "*.jar" -follow >> .jarlist -
diff -N java-run.sh --- java-run.sh 27 May 2011 12:01:14 -0000 1.1 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,17 +0,0 @@
-#!/bin/bash - -echo Started... - -source exportCLASSPATH.sh - -SKIP=$1 -NUM=$2 -SOURCE=`cat $3` -CLASSNAME=$4 - -echo "SOURCE is '$SOURCE'" -echo "CLASSPATH is $CLASSPATH" - -echo Start MainLoop... -java -classpath $CLASSPATH -Xmx2048m org.lcsim.contrib.uiowa.MainLoop $SKIP $NUM $CLASSNAME $SOURCE -echo Done
diff -N macro-run.sh --- macro-run.sh 27 May 2011 12:01:14 -0000 1.1 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,9 +0,0 @@
-#!/bin/bash - -if [ $# -ne 1 ] ; then - echo "Usage: `basename $0` <className>" -fi - -source exportCLASSPATH.sh - -java -classpath $CLASSPATH $1 $@
diff -N mergeAIDAFiles.sh --- mergeAIDAFiles.sh 27 May 2011 12:01:14 -0000 1.1 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,3 +0,0 @@
-#!/bin/bash - -./macro-run.sh org.lcsim.contrib.uiowa.uiowapfa.macros.Merge $@
diff -N mergeLikelihoodFiles.sh --- mergeLikelihoodFiles.sh 27 May 2011 14:14:04 -0000 1.1 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,5 +0,0 @@
-#!/bin/bash - -./macro-run.sh org.lcsim.contrib.uiowa.uiowapfa.recon.cluster.structural.likelihood.MergeLikelihoodFiles $@ - -
diff -N normalize.sh --- normalize.sh 27 May 2011 12:01:14 -0000 1.1 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,3 +0,0 @@
-#!/bin/bash - -./macro-run.sh org.lcsim.contrib.uiowa.uiowapfa.macros.Normalize $@
diff -N plotLikelihoods.sh --- plotLikelihoods.sh 27 May 2011 12:01:14 -0000 1.1 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,3 +0,0 @@
-#!/bin/bash - -./macro-run.sh org.lcsim.contrib.uiowa.uiowapfa.recon.cluster.structural.likelihood.PlotLikelihoods $@
diff -N run-pfa.sh --- run-pfa.sh 27 May 2011 12:01:14 -0000 1.1 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,10 +0,0 @@
-#!/bin/bash - -if [ $# -ne 3 ] -then - echo "Usage: `basename $0` <skip events> <max events> <input list>" - exit -fi - -./java-run.sh $1 $2 $3 org.lcsim.contrib.uiowa.uiowapfa.recon.pfa.structural.RunAndWriteOutPFAFullTracking -
diff -N submit.sh --- submit.sh 27 May 2011 13:08:48 -0000 1.1 +++ /dev/null 1 Jan 1970 00:00:00 -0000 @@ -1,106 +0,0 @@
-#!/bin/csh - -##-- This is input section -##-- Default values are defined here -##-- All values can be changed from command line -@ eventsPerJob = 50 -@ eventsPerFile = 500 -set nfshome = /nfs/slac/g/uiowa/u01/zaidan/batch/joboutputs -set workdir = $nfshome/testJob -set queue = long # xlong # xxl # -set inputList = list -############################### - -set scriptname = $0 -set label = main -goto $label - -printHelp: - echo "" - echo "Usage $scriptname [options [option arguments]] [workdir]" - echo "" - echo " [workdir] is the path where the job should run relative to the nfs home specified by the --nfs option" - echo " Options are:" - echo " -h,--help: prints this help message and exits" - echo " -n,--eventsPerJob number: number of events per job [default: $eventsPerJob]" - echo " -N,--eventsPerFile number: number of events per file [default: $eventsPerFile]" - echo " --nfs path: absolute path to the nfs home [default: $nfshome]" - echo " -q,--queue queueName: name of the batch queue where to send the job [default: $queue]" - echo " -i,--input file: text file containing a list of input files [default: $inputList]" - echo "" - echo " N.B.: It is important that the [workdir] argument is passed after setting the --nfs option" - echo "" - goto $label - -main: - -set workdirSet = false -while ($#argv != 0) - set arg = $1 - if( "$arg" == "--help" || "$arg" == "-h" ) then - set label = done - goto printHelp - endif - if( "$arg" == "--eventsPerJob" || "$arg" == "-n" ) then - shift - @ eventsPerJob = $1 - else if( "$arg" == "--eventsPerFile" || "$arg" == "-N" ) then - shift - @ eventsPerFile = $1 - else if( "$arg" == "--nfs" ) then - shift - if( $workdirSet == true) then - echo "Warning: the --nfs option should be set before the [workdir] argument: option ignored" - echo " type $scriptname --help for more info" - else - set nfshome = $1 - endif - else if( "$arg" == "--queue" || "$arg" == "-q" ) then - shift - set queue = $1 - else if( "$arg" == "--input" || "$arg" == "-i" ) then - shift - set inputList = $1 - else - set workdir = $nfshome/$1 - set workdirSet = true - endif - shift -end - -set curdir = `pwd` - -rm -rf $workdir -mkdir -p $workdir -cp java-init-cache.sh $workdir -cd $workdir -./java-init-cache.sh -cd $curdir - -@ i = 0 -@ jobsPerFile = $eventsPerFile / $eventsPerJob - -foreach f (`cat $inputList`) - @ j = 0 - @ skip = 0 - while($j < $jobsPerFile) - set jobdir = $workdir/$i - rm -rf $jobdir - mkdir -p $jobdir - cp exportCLASSPATH.sh $jobdir - cp java-run.sh $jobdir - cp run-pfa.sh $jobdir - ln -s $workdir/.jarlist $jobdir/.jarlist - ln -s $workdir/.workdir $jobdir/.workdir - echo $f > $jobdir/list - echo "cd $jobdir; ./run-pfa.sh $skip $eventsPerJob list | grep -v WARNING;" > $jobdir/run.sh - chmod a+x $jobdir/run.sh - bsub -q $queue -R linux -J $1_$i -o $jobdir/job.log $jobdir/run.sh - @ skip = $skip + $eventPerJob - @ i = $i + 1 - @ j = $j + 1 - end -end - -done: - exit
Use REPLY-ALL to reply to list
To unsubscribe from the LCD-CVS list, click the following link:
https://listserv.slac.stanford.edu/cgi-bin/wa?SUBED1=LCD-CVS&A=1