Print

Print


Commit in lcsim/src/org/lcsim/recon/cluster on MAIN
cheat/ClusterCheater.java-451.3 removed
     /CreateCheatClusters.java-591.1 removed
fixedcone/FixedConeClusterer.java+300-271.4 -> 1.5
         /CreateFCClusters.java-2951.1 removed
nn/NearestNeighborCluster.java+66-661.5 -> 1.6
  /NearestNeighborClusterer.java+72-871.6 -> 1.7
  /CreateNNClusters.java-901.1 removed
util/BasicCluster.java+279-2791.2 -> 1.3
    /TensorClusterPropertyCalculator.java+272-2711.2 -> 1.3
    /FCClusterPropertyCalculator.java-3301.1 removed
+989-1549
5 removed + 5 modified, total 10 files
Refactored clustering classes.

lcsim/src/org/lcsim/recon/cluster/cheat
ClusterCheater.java removed after 1.3
diff -N ClusterCheater.java
--- ClusterCheater.java	8 Jul 2005 17:15:05 -0000	1.3
+++ /dev/null	1 Jan 1970 00:00:00 -0000
@@ -1,45 +0,0 @@
-package org.lcsim.recon.cluster.cheat;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import org.lcsim.event.Cluster;
-import org.lcsim.event.EventHeader;
-import org.lcsim.event.MCParticle;
-import org.lcsim.event.SimCalorimeterHit;
-import org.lcsim.recon.cluster.util.BasicCluster;
-import org.lcsim.util.Driver;
-
-
-/**
- * Driver to create and write CheatClusters to the event
- */
-
-public class ClusterCheater extends Driver
-{
-   CreateCheatClusters ccc;
-   public ClusterCheater()
-   {
-	  ccc = new CreateCheatClusters();
-   }
-   
-   public void process(EventHeader event)
-   {
-      //First look for clusters in individual collections
-      
-      List<List<SimCalorimeterHit>> collections = event.get(SimCalorimeterHit.class);
-      for (List<SimCalorimeterHit> collection : collections)
-      {
-         Map<MCParticle,CheatCluster> result = ccc.findClusters(collection);
-         String name = event.getMetaData(collection).getName();
-         if (result.size() > 0) event.put(name+"Clusters",new ArrayList(result.values()));
-      }
-      
-      // Then look for refined clusters combining hits from all collections
-      
-      List<List<CheatCluster>> clusters = event.get(CheatCluster.class);
-      Map<MCParticle, CheatCluster> refined = ccc.findRefinedClusters(clusters);
-      if (refined.size() > 0) event.put("RefinedClusters",new ArrayList(refined.values()));
-   }
-}

lcsim/src/org/lcsim/recon/cluster/cheat
CreateCheatClusters.java removed after 1.1
diff -N CreateCheatClusters.java
--- CreateCheatClusters.java	8 Jul 2005 17:15:05 -0000	1.1
+++ /dev/null	1 Jan 1970 00:00:00 -0000
@@ -1,59 +0,0 @@
-package org.lcsim.recon.cluster.cheat;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import org.lcsim.event.Cluster;
-import org.lcsim.event.MCParticle;
-import org.lcsim.event.SimCalorimeterHit;
-import org.lcsim.recon.cluster.util.BasicCluster;
-
-
-/**
- * The Cluster cheater works by finding perfectly reconstructed clusters
- * based by looking at the MC truth information associated with each hit.
- *
- * To simplify the coding for now, if more than one MC particle is associated with a
- * single hit, the entire hit is associated with the cluster belonging to the MC
- * particle that contributed the most energy to the hit. Note that there is currently
- * no attempt to merge clusters that would in fact be impossible to resolve.
- */
-
-public class CreateCheatClusters
-{
-   
-   public Map<MCParticle, CheatCluster> findClusters(List<SimCalorimeterHit> hits)
-   {
-      Map<MCParticle,CheatCluster> result = new HashMap<MCParticle,CheatCluster>();
-      for (SimCalorimeterHit hit : hits)
-      {        
-         double eMax = hit.getContributedEnergy(0);
-         MCParticle pMax = hit.getMCParticle(0);
-         for (int i=1; i<hit.getMCParticleCount(); i++)
-         {
-            if (hit.getContributedEnergy(i) > eMax) pMax = hit.getMCParticle(i);
-         }
-         CheatCluster cc = result.get(pMax);
-         if (cc == null) result.put(pMax,cc = new CheatCluster(pMax));
-         cc.addHit(hit);        
-      }
-      return result;
-   }
-   public Map<MCParticle, CheatCluster> findRefinedClusters(List<List<CheatCluster>> collections)
-   {
-      Map<MCParticle, CheatCluster> result = new HashMap<MCParticle,CheatCluster>();
-      for (List<CheatCluster> clusters : collections)
-      {
-         for (CheatCluster cluster : clusters)
-         {
-            MCParticle p = cluster.getMCParticle();
-            CheatCluster rc = result.get(p);
-            if (rc == null) result.put(p,rc = new CheatCluster(p));
-            rc.addCluster(cluster);
-         }
-      }
-      return result;
-   }
-   
-}

lcsim/src/org/lcsim/recon/cluster/fixedcone
FixedConeClusterer.java 1.4 -> 1.5
diff -u -r1.4 -r1.5
--- FixedConeClusterer.java	8 Jul 2005 17:15:06 -0000	1.4
+++ FixedConeClusterer.java	18 Jul 2005 03:06:18 -0000	1.5
@@ -2,16 +2,13 @@
 
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
 import org.lcsim.event.CalorimeterHit;
-import org.lcsim.event.EventHeader;
-import org.lcsim.event.SimCalorimeterHit;
 import org.lcsim.event.util.CalorimeterHitEsort;
 import org.lcsim.geometry.CalorimeterIDDecoder;
-import org.lcsim.recon.cluster.util.*;
-import org.lcsim.util.Driver;
+import org.lcsim.recon.cluster.util.BasicCluster;
+import org.lcsim.recon.cluster.util.ClusterESort;
+import org.lcsim.recon.cluster.util.FixedConeClusterPropertyCalculator;
 import org.lcsim.util.fourvec.Lorentz4Vector;
 import org.lcsim.util.fourvec.Momentum4Vector;
 
@@ -28,58 +25,334 @@
  * @version 1.0
  */
 
-public class FixedConeClusterer extends Driver
+public class FixedConeClusterer
 {
     private double _radius;
-    private double _Eseed;
-    private double _Emin;
+    private double _seedEnergy;
+    private double _minEnergy;
     private int _numLayers;
     private double _samplingFraction;
     private double[] _layerEnergy;
-	private CreateFCClusters clusterer;
     
-    CalorimeterIDDecoder _decoder;
     
     private static final double PI=Math.PI;
     private static final double TWOPI = 2.*PI;
+    public FixedConeClusterPropertyCalculator _clusterPropertyCalculator;
     
+    private FixedConeDistanceMetric _dm;
+    
+    public enum FixedConeDistanceMetric
+    { DOTPRODUCT, DPHIDCOSTHETA, DPHIDTHETA }
     /**
      * Constructor
      *
      * @param   radius The cone radius in <font face="symbol">q-f </font> space
      * @param   seed   The minimum energy for a cone seed cell (in GeV)
      * @param   minE   The minimum energy for a cluster (in GeV)
+     * @param   distMetric The distance metric:
+     *                     0 for dot-product method,
+     *                     1 for R<sup>2</sup> = (d phi)<sup>2 + (d(cos theta))<sup>2</sup>
+     *                       (simplified version of dot-product method)
+     *                     2 for R<sup>2</sup> = (d phi)<sup>2 + (d theta)<sup>2</sup>
+     *                       (backwards compatibility mode with old FixedConeClusterer implementation
+     *                     Anything else will be assumed to be 0.
      */
-    public FixedConeClusterer(double radius, double seed, double minE)
+    public FixedConeClusterer(double radius, double seed, double minE, FixedConeDistanceMetric distMetric)
     {
         _radius = radius;
         // overwrite later with sampling fraction correction
-        _Eseed = seed;
-        _Emin = minE;
-		clusterer = new CreateFCClusters(_radius, _Eseed, _Emin);
-	}
+        _seedEnergy = seed;
+        _minEnergy = minE;
+        _dm = distMetric;
+    }
+    /**
+     * Constructor with default distance metric (dot-product method)
+     *
+     * @param   radius The cone radius in <font face="symbol">q-f </font> space
+     * @param   seed   The minimum energy for a cone seed cell (in GeV)
+     * @param   minE   The minimum energy for a cluster (in GeV)
+     */
+    public FixedConeClusterer(double radius, double seed, double minE)
+    {
+        this(radius, seed, minE, FixedConeDistanceMetric.DOTPRODUCT);
+    }
+    
+/*
+    public void setRadius(double radius)
+    {
+        _radius = radius;
+    }
+    public void setSeed(double seed)
+    {
+        _seedEnergy = seed;
+    }
+    public void setMinE(double minE)
+    {
+        _minEnergy = minE;
+    }
+ */
+    
+    /**
+     * Make clusters from the input list
+     */
+    public List<BasicCluster> makeClusters(List<CalorimeterHit> in, CalorimeterIDDecoder decoder)
+    {
+        List<BasicCluster> out = new ArrayList<BasicCluster>();
+        _clusterPropertyCalculator = new FixedConeClusterPropertyCalculator(decoder);
+        
+        double rsquared = _radius*_radius;
+        // sort the vector in descending energy for efficiency
+        // this starts with the highest energy seeds.
+        Collections.sort(in, new CalorimeterHitEsort());
+        
+        int nclus = 0;
+        int size = in.size();
+        boolean[] used = new boolean[size];
+        //   outer loop finds a seed
+        for(int i =0; i<size; ++i)
+        {
+            if (!used[i])
+            {
+                CalorimeterHit p = in.get(i);
+                if (p.getEnergy()>_seedEnergy)
+                {
+                    decoder.setID(p.getCellID());
+                    double cellE = p.getEnergy();
+                    double px = cellE*Math.cos(decoder.getPhi())*Math.sin(decoder.getTheta());
+                    double py = cellE*Math.sin(decoder.getPhi())*Math.sin(decoder.getTheta());
+                    double pz = cellE*Math.cos(decoder.getTheta());
+                    Lorentz4Vector sum = new Momentum4Vector(px,py,pz,cellE);
+                    double phiseed=sum.phi();
+                    double thetaseed=sum.theta();
+                    
+                    // constituent cells
+                    List<CalorimeterHit> members = new ArrayList<CalorimeterHit>();
+                    members.add(p);
+                    // inner loop adds neighboring cells to seed
+                    
+                    for (int j = i+1; j<size; ++j)
+                    {
+                        //                        if (in.get(j)!=null)
+                        if(!used[j])
+                        {
+                            CalorimeterHit p2 = in.get(j);
+                            decoder.setID(p2.getCellID());
+                            double phi = decoder.getPhi();
+                            double theta=decoder.getTheta();
+                            double dphi=phi-phiseed;
+                            
+                            if(dphi<-PI) dphi+=TWOPI;
+                            if(dphi>PI) dphi-=TWOPI;
+                            double dtheta = theta-thetaseed;
+                            double R2 = 0;
+                            boolean cond = false;
+                            
+                            switch(_dm)
+                            {
+                                case DPHIDCOSTHETA: // R^2 = dphi^2 + d(cos theta)^2
+                                    double dcostheta = Math.cos(theta)-Math.cos(thetaseed);
+                                    R2 = dphi*dphi + dcostheta*dcostheta;
+                                    cond = (R2 < rsquared);
+                                    break;
+                                case DPHIDTHETA: // R^2 = dphi^2 + dtheta^2
+                                    R2 = dphi*dphi + dtheta*dtheta;
+                                    cond = (R2 < rsquared);
+                                    break;
+                                case DOTPRODUCT:
+                                default: // dot product method
+                                    double dotp = Math.sin(theta)*Math.sin(thetaseed)*
+                                            (Math.sin(phi)*Math.sin(phiseed) +
+                                            Math.cos(phi)*Math.cos(phiseed)) +
+                                            Math.cos(theta)*Math.cos(thetaseed);
+                                    cond = (dotp > Math.cos(_radius));
+                                    break;
+                            }
+                            
+                            if(cond)
+                            {
+                                //  particle within cone
+                                cellE = p2.getEnergy();
+                                px = cellE*Math.cos(decoder.getPhi())*Math.sin(decoder.getTheta());
+                                py = cellE*Math.sin(decoder.getPhi())*Math.sin(decoder.getTheta());
+                                pz = cellE*Math.cos(decoder.getTheta());
+                                sum.plusEquals(new Momentum4Vector(px, py, pz, cellE));
+                                members.add(p2);
+                                // tag this element so we don't reuse it
+                                used[j]=true;
+                                
+                                //   recalculate cone center
+                                phiseed=sum.phi();
+                                thetaseed=sum.theta();
+                            }
+                        }
+                    }// end of inner loop
+                    
+                    
+                    // if energy of cluster is large enough add it to the list
+                    if(sum.E()>_minEnergy)
+                    {
+                        BasicCluster clus = new BasicCluster();
+                        clus.setPropertyCalculator(_clusterPropertyCalculator);
+                        for(CalorimeterHit hit : members)
+                        {
+                            clus.addHit(hit);
+                        }
+                        out.add(clus);
+                        nclus++;
+                    }
+                    
+                }
+            }// end of outer loop
+        }
+        
+        if (nclus>1)
+        {
+            // sort the clusters in descending energy
+            Collections.sort(out, new ClusterESort());
+            // loop over the found clusters and look for overlaps
+            // i.e distance between clusters is less than 2*R
+            for(int i=0; i<out.size();++i  )
+            {
+                for(int j=i+1; j<out.size(); ++j)
+                {
+                    double dTheta = dTheta(out.get(i), out.get(j));
+                    if (dTheta<2*_radius)
+                    {
+                        resolve(out.get(i), out.get(j), decoder);
+                    }
+                }
+            }
+        }
+        
+//        System.out.println("found "+out.size()+ " clusters");
+        return out;
+    }
     
     
     /**
-     * Processes an Event to find CalorimeterClusters
+     * Calculate the angle between two Clusters
      *
-     * @param   event  The Event to process
+     * @param   c1  First Cluster
+     * @param   c2  Second Cluster
+     * @return     The angle between the two clusters
      */
-    public void process(EventHeader event)
+    
+    public double dTheta(BasicCluster c1, BasicCluster c2)
+    {
+        _clusterPropertyCalculator.calculateProperties(c1.getCalorimeterHits());
+        Lorentz4Vector v1 = _clusterPropertyCalculator.vector();
+        _clusterPropertyCalculator.calculateProperties(c2.getCalorimeterHits());
+        Lorentz4Vector v2 = _clusterPropertyCalculator.vector();
+        double costheta = (v1.vec3dot(v2))/(v1.p()*v2.p());
+        return Math.acos(costheta);
+    }
+    
+    /**
+     * Given two overlapping clusters, assign cells to nearest axis.
+     * The cluster axes are <em> not </em> iterated.
+     * Cluster quantities are recalculated after the split.
+     *
+     * @param   c1 First Cluster
+     * @param   c2 Second Cluster
+     */
+    
+    public void resolve(BasicCluster c1, BasicCluster c2, CalorimeterIDDecoder decoder)
     {
-        List<CalorimeterHit> collection = event.get(CalorimeterHit.class,"EcalBarrHits");
-        _decoder = (CalorimeterIDDecoder) event.getMetaData(collection).getIDDecoder();
-//        System.out.println(_decoder);
-        List<BasicCluster> clusters = clusterer.makeClusters(collection,_decoder);
+        // do not recalculate cluster axis until all reshuffling is done
+        // do not want the cones to shift
+        // this behavior may change in the future
         
-        String name = event.getMetaData(collection).getName();
-        if (clusters.size() > 0) event.put(name+"FCClusters",clusters);
+        _clusterPropertyCalculator.calculateProperties(c1.getCalorimeterHits());
+        Lorentz4Vector v1 = _clusterPropertyCalculator.vector();
+        double phi1 = v1.phi();
+        double theta1 = v1.theta();
+        _clusterPropertyCalculator.calculateProperties(c2.getCalorimeterHits());
+        Lorentz4Vector v2 = _clusterPropertyCalculator.vector();
+        double phi2 = v2.phi();
+        double theta2 = v2.theta();
+        List<CalorimeterHit> cells1 = c1.getCalorimeterHits();
+        List<CalorimeterHit> cells2 = c2.getCalorimeterHits();
+        int size2 = cells2.size();
         
+        List<CalorimeterHit> tmp = new ArrayList<CalorimeterHit>();
+        // loop over cells in first cluster...
+        for(int i=0; i<cells1.size(); ++i)
+        {
+            CalorimeterHit p2 = (CalorimeterHit) cells1.get(i);
+            decoder.setID(p2.getCellID());
+            double phi = decoder.getPhi();
+            double theta = decoder.getTheta();
+            //distance to cluster 1
+            double dphi1=phi-phi1;
+            if(dphi1<-PI) dphi1+=TWOPI;
+            if(dphi1>PI) dphi1-=TWOPI;
+            double dtheta1 = theta-theta1;
+            double R1=dphi1*dphi1+(dtheta1)*(dtheta1);
+            // distance to cluster 2
+            double dphi2=phi-phi2;
+            if(dphi2<-PI) dphi2+=TWOPI;
+            if(dphi2>PI) dphi2-=TWOPI;
+            double dtheta2 = theta-theta2;
+            double R2=dphi2*dphi2+(dtheta2)*(dtheta2);
+            
+            if (R2<R1)
+            {
+                //add this cell to the vector of cells to remove
+                tmp.add(p2);
+            }
+        }
+        for(int i=0; i<tmp.size(); ++i)
+        {
+            CalorimeterHit p2 = (CalorimeterHit) tmp.get(i);
+            // remove this cell from cluster1
+            cells1.remove(p2);
+            // add it to cluster2
+            cells2.add(p2);
+        }
+        tmp.clear();
+        // repeat for cluster 2
+        // only loop over cells in original cluster
+        for(int i=0; i<size2; ++i)
+        {
+            CalorimeterHit p2 = (CalorimeterHit) cells2.get(i);
+            decoder.setID(p2.getCellID());
+            double phi = decoder.getPhi();
+            double theta = decoder.getTheta();
+            //distance to cluster 1
+            double dphi1=phi-phi1;
+            if(dphi1<-PI) dphi1+=TWOPI;
+            if(dphi1>PI) dphi1-=TWOPI;
+            double dtheta1 = theta-theta1;
+            double R1=dphi1*dphi1+(dtheta1)*(dtheta1);
+            // distance to cluster 2
+            double dphi2=phi-phi2;
+            if(dphi2<-PI) dphi2+=TWOPI;
+            if(dphi2>PI) dphi2-=TWOPI;
+            double dtheta2 = theta-theta2;
+            double R2=dphi2*dphi2+(dtheta2)*(dtheta2);
+            
+            if (R1<R2)
+            {
+                //add this cell to the vector of cells to remove
+                tmp.add(p2);
+            }
+        }
+        for(int i=0; i<tmp.size(); ++i)
+        {
+            CalorimeterHit p2 = (CalorimeterHit) tmp.get(i);
+            // remove this cell from cluster2
+            cells2.remove(p2);
+            // add it to cluster1
+            cells1.add(p2);
+        }
+        
+        c1.calculateProperties();
+        c2.calculateProperties();
     }
-   
+    
     
     public String toString()
     {
-        return "FixedConeClusterer with radius "+_radius+" seed Energy "+_Eseed+" minimum energy "+_Emin;
+        return "FixedConeClusterer with radius "+_radius+" seed Energy "+_seedEnergy+" minimum energy "+_minEnergy+"distance metric "+_dm;
     }
 }

lcsim/src/org/lcsim/recon/cluster/fixedcone
CreateFCClusters.java removed after 1.1
diff -N CreateFCClusters.java
--- CreateFCClusters.java	8 Jul 2005 17:15:06 -0000	1.1
+++ /dev/null	1 Jan 1970 00:00:00 -0000
@@ -1,295 +0,0 @@
-package org.lcsim.recon.cluster.fixedcone;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import org.lcsim.event.CalorimeterHit;
-import org.lcsim.event.EventHeader;
-import org.lcsim.event.SimCalorimeterHit;
-import org.lcsim.event.util.CalorimeterHitEsort;
-import org.lcsim.geometry.CalorimeterIDDecoder;
-import org.lcsim.recon.cluster.util.*;
-import org.lcsim.util.Driver;
-import org.lcsim.util.fourvec.Lorentz4Vector;
-import org.lcsim.util.fourvec.Momentum4Vector;
-
-/**
- * FixedConeClusterer implements a
- * <font face="symbol">q-f </font> cone clustering algorithm
- * that assigns all neighboring hits to the same cluster if they fall
- * within a radius R of the cluster axis. The axis is originally defined
- * by a seed cell, and is iteratively updated as cells are added.
- * This version of the ClusterBuilder splits overlapping clusters
- * by assigning cells in the overlap region to the nearest cluster axis.
- *
- * @author Norman A. Graf
- * @version 1.0
- */
-
-public class CreateFCClusters 
-{
-    private double _radius;
-    private double _Eseed;
-    private double _Emin;
-    private int _numLayers;
-    private double _samplingFraction;
-    private double[] _layerEnergy;
-    
-    CalorimeterIDDecoder _decoder;
-    
-    private static final double PI=Math.PI;
-    private static final double TWOPI = 2.*PI;
-	public FCClusterPropertyCalculator cpc;
-    
-    /**
-     * Constructor
-     *
-     * @param   radius The cone radius in <font face="symbol">q-f </font> space
-     * @param   seed   The minimum energy for a cone seed cell (in GeV)
-     * @param   minE   The minimum energy for a cluster (in GeV)
-     */
-    public CreateFCClusters(double radius, double seed, double minE)
-    {
-        _radius = radius;
-        // overwrite later with sampling fraction correction
-        _Eseed = seed;
-        _Emin = minE;
-    }
-	public void setRadius(double radius)
-	{
-		_radius = radius;
-	}
-	public void setSeed(double seed)
-	{
-		_Eseed = seed;
-	}
-	public void setMinE(double minE)
-	{
-		_Emin = minE;
-	}
-    
-    
-    /**
-     * Make clusters from the input list
-     */
-    public List<BasicCluster> makeClusters(List<CalorimeterHit> in, CalorimeterIDDecoder decoder)
-    {
-        List<BasicCluster> out = new ArrayList<BasicCluster>();
-		cpc = new FCClusterPropertyCalculator(decoder);
-        
-        double rsquared = _radius*_radius;
-        // sort the vector in descending energy for efficiency
-        // this starts with the highest energy seeds.
-        Collections.sort(in, new CalorimeterHitEsort());
-        
-        int nclus = 0;
-        int size = in.size();
-        boolean[] used = new boolean[size];
-        //   outer loop finds a seed
-        for(int i =0; i<size; ++i)
-        {
-            if (!used[i])
-            {
-                CalorimeterHit p = in.get(i);
-                if (p.getEnergy()>_Eseed)
-                {
-                    decoder.setID(p.getCellID());
-                    double cellE = p.getEnergy();
-                    double px = cellE*Math.cos(decoder.getPhi())*Math.sin(decoder.getTheta());
-                    double py = cellE*Math.sin(decoder.getPhi())*Math.sin(decoder.getTheta());
-                    double pz = cellE*Math.cos(decoder.getTheta());
-                    Lorentz4Vector sum = new Momentum4Vector(px,py,pz,cellE);
-                    double phiseed=sum.phi();
-                    double thetaseed=sum.theta();
-                    
-                    // constituent cells
-                    List<CalorimeterHit> members = new ArrayList<CalorimeterHit>();
-                    members.add(p);
-                    // inner loop adds neighboring cells to seed
-                    
-                    for (int j = i+1; j<size; ++j)
-                    {
-                        //                        if (in.get(j)!=null)
-                        if(!used[j])
-                        {
-                            CalorimeterHit p2 = in.get(j);
-                            decoder.setID(p2.getCellID());
-                            double phi = decoder.getPhi();
-                            double theta=decoder.getTheta();
-                            double dphi=phi-phiseed;
-                            
-                            if(dphi<-PI) dphi+=TWOPI;
-                            if(dphi>PI) dphi-=TWOPI;
-                            double dtheta = theta-thetaseed;
-                            double R2=dphi*dphi+dtheta*dtheta;
-                            if(R2< rsquared)
-                            {
-                                //  particle within cone
-                                cellE = p2.getEnergy();
-                                px = cellE*Math.cos(decoder.getPhi())*Math.sin(decoder.getTheta());
-                                py = cellE*Math.sin(decoder.getPhi())*Math.sin(decoder.getTheta());
-                                pz = cellE*Math.cos(decoder.getTheta());
-                                sum.plusEquals(new Momentum4Vector(px, py, pz, cellE));
-                                members.add(p2);
-                                // tag this element so we don't reuse it
-                                used[j]=true;
-                                
-                                //   recalculate cone center
-                                phiseed=sum.phi();
-                                thetaseed=sum.theta();
-                            }
-                        }
-                    }// end of inner loop
-                    
-                    
-                    // if energy of cluster is large enough add it to the list
-                    if(sum.E()>_Emin)
-                    {
-                        BasicCluster clus = new BasicCluster();
-						clus.setPropertyCalculator(cpc);
-                        for(CalorimeterHit hit : members)
-                        {
-                            clus.addHit(hit);
-                        }
-                        out.add(clus);
-                        nclus++;
-                    }
-                    
-                }
-            }// end of outer loop
-        }
-
-        if (nclus>1)
-        {
-            // sort the clusters in descending energy
-            Collections.sort(out, new ClusterESort());
-            // loop over the found clusters and look for overlaps
-            // i.e distance between clusters is less than 2*R
-            for(int i=0; i<out.size();++i  )
-            {
-                for(int j=i+1; j<out.size(); ++j)
-                {
-                    double dTheta = dTheta((BasicCluster)out.get(i), (BasicCluster)out.get(j));
-                    if (dTheta<2*_radius)
-                    {
-//                        resolve((BasicCluster)out.get(i), (BasicCluster)out.get(j));
-                    }
-                }
-            }
-        }
-
-//        System.out.println("found "+out.size()+ " clusters");
-        return out;
-    }
-    
-    
-    /**
-     * Calculate the angle between two Clusters
-     *
-     * @param   c1  First Cluster
-     * @param   c2  Second Cluster
-     * @return     The angle between the two clusters
-     */
-    
-    public double dTheta(BasicCluster c1, BasicCluster c2)
-    {
-		cpc.calculateProperties(c1.getCalorimeterHits());
-        Lorentz4Vector v1 = cpc.vector();
-		cpc.calculateProperties(c2.getCalorimeterHits());
-		Lorentz4Vector v2 = cpc.vector();
-        double costheta = (v1.vec3dot(v2))/(v1.p()*v2.p());
-        return Math.acos(costheta);
-    }
-     
-    /**
-     * Given two overlapping clusters, assign cells to nearest axis.
-     * The cluster axes are <em> not </em> iterated.
-     * Cluster quantities are recalculated after the split.
-     *
-     * @param   c1 First Cluster
-     * @param   c2 Second Cluster
-     */
-    
-    public void resolve(BasicCluster c1, BasicCluster c2)
-    {
-        // do not recalculate cluster axis until all reshuffling is done
-        // do not want the cones to shift
-        // this behavior may change in the future
-     
-		cpc.calculateProperties(c1.getCalorimeterHits());
-		Lorentz4Vector v1 = cpc.vector();
-        double phi1 = v1.phi();
-        double theta1 = v1.theta();
-		cpc.calculateProperties(c2.getCalorimeterHits());
-		Lorentz4Vector v2 = cpc.vector();
-        double phi2 = v2.phi();
-        double theta2 = v2.theta();
-        List<CalorimeterHit> cells1 = c1.getCalorimeterHits();
-        List<CalorimeterHit> cells2 = c2.getCalorimeterHits();
-        int size2 = cells2.size();
-     
-        List<CalorimeterHit> tmp = new ArrayList<CalorimeterHit>();
-        // loop over cells in first cluster...
-        for(int i=0; i<cells1.size(); ++i)
-        {
-            CalorimeterHit p2 = (CalorimeterHit) cells1.get(i);
-            _decoder.setID(p2.getCellID());
-            double phi = _decoder.getPhi();
-            double theta = _decoder.getTheta();
-            //distance to cluster 1
-            double dphi1=phi-phi1;
-            if(dphi1<-PI) dphi1+=TWOPI;
-            if(dphi1>PI) dphi1-=TWOPI;
-            double dtheta1 = theta-theta1;
-            double R1=dphi1*dphi1+(dtheta1)*(dtheta1);
-            // distance to cluster 2
-            double dphi2=phi-phi2;
-            if(dphi2<-PI) dphi2+=TWOPI;
-            if(dphi2>PI) dphi2-=TWOPI;
-            double dtheta2 = theta-theta2;
-            double R2=dphi2*dphi2+(dtheta2)*(dtheta2);
-     
-            if (R2<R1)
-            {
-				c1.removeHit(p2);
-				c2.addHit(p2);
-            }
-        }
-        tmp.clear();
-        // repeat for cluster 2
-        // only loop over cells in original cluster
-        for(int i=0; i<size2; ++i)
-        {
-            CalorimeterHit p2 = (CalorimeterHit) cells2.get(i);
-            _decoder.setID(p2.getCellID());
-            double phi = _decoder.getPhi();
-            double theta = _decoder.getTheta();
-            //distance to cluster 1
-            double dphi1=phi-phi1;
-            if(dphi1<-PI) dphi1+=TWOPI;
-            if(dphi1>PI) dphi1-=TWOPI;
-            double dtheta1 = theta-theta1;
-            double R1=dphi1*dphi1+(dtheta1)*(dtheta1);
-            // distance to cluster 2
-            double dphi2=phi-phi2;
-            if(dphi2<-PI) dphi2+=TWOPI;
-            if(dphi2>PI) dphi2-=TWOPI;
-            double dtheta2 = theta-theta2;
-            double R2=dphi2*dphi2+(dtheta2)*(dtheta2);
-     
-            if (R1<R2)
-            {
-				c2.removeHit(p2);
-				c1.addHit(p2);
-            }
-        }
-    }
-     
-    
-    public String toString()
-    {
-        return "FixedConeClusterer with radius "+_radius+" seed Energy "+_Eseed+" minimum energy "+_Emin;
-    }
-}

lcsim/src/org/lcsim/recon/cluster/nn
NearestNeighborCluster.java 1.5 -> 1.6
diff -u -r1.5 -r1.6
--- NearestNeighborCluster.java	8 Jul 2005 17:15:07 -0000	1.5
+++ NearestNeighborCluster.java	18 Jul 2005 03:06:19 -0000	1.6
@@ -13,72 +13,72 @@
  */
 public class NearestNeighborCluster extends BasicCluster
 {
-   /**
-    * Construct a NearestNeighborCluster. Note that the constructor actually performs the
-    * clustering, given a seed hit.
-    * @param decoder The CellID decoder appropriate for this collection of hits.
-    * @param hitmap The list of hit calorimeter cells available for clustering.
-    * @param hit The seed calorimeter hit for this cluster.
-    * @param key The key for the seed calorimeter hit.
-    * @param threshold The energy threshold that must be met or exceeded in order
-    *   to be considered in the cluster.
-    */
-   
-   public NearestNeighborCluster(CalorimeterIDDecoder decoder, Map<Long, CalorimeterHit> hitmap, CalorimeterHit hit, Long key, int dU, int dV, int dLayer, double threshold)
-   {
-      // start by adding this hit to the cluster
-      addHit(hit);
-      
-      // set the decoder to this hit
-      decoder.setID(key);
-      // remove this hit from the map so it can't be used again
-      hitmap.remove(key);
-      
-      //  loop over the hits in the cluster and add all its neighbors
-      // note that hits.size() grows as we add cells
-      for(int i=0; i<hits.size(); ++i)
-      {
-         CalorimeterHit c = hits.get(i);
-         decoder.setID(c.getCellID());
-         
-         long[] neighbors = decoder.getNeighbourIDs(dLayer, dU, dV);
-         // loop over all neighboring cell Ids
-         for (int j=0; j<neighbors.length; ++j)
-         {
-            CalorimeterHit h = hitmap.get(neighbors[j]);
-            // is the neighboring cell id hit?
-            // if so, does it meet or exceed threshold?
-            if (h != null)
+    /**
+     * Construct a NearestNeighborCluster. Note that the constructor actually performs the
+     * clustering, given a seed hit.
+     * @param decoder The CellID decoder appropriate for this collection of hits.
+     * @param hitmap The list of hit calorimeter cells available for clustering.
+     * @param hit The seed calorimeter hit for this cluster.
+     * @param key The key for the seed calorimeter hit.
+     * @param threshold The energy threshold that must be met or exceeded in order
+     *   to be considered in the cluster.
+     */
+    
+    public NearestNeighborCluster(CalorimeterIDDecoder decoder, Map<Long, CalorimeterHit> hitmap, CalorimeterHit hit, Long key, int dU, int dV, int dLayer, double threshold)
+    {
+        // start by adding this hit to the cluster
+        addHit(hit);
+        
+        // set the decoder to this hit
+        decoder.setID(key);
+        // remove this hit from the map so it can't be used again
+        hitmap.remove(key);
+        
+        //  loop over the hits in the cluster and add all its neighbors
+        // note that hits.size() grows as we add cells
+        for(int i=0; i<hits.size(); ++i)
+        {
+            CalorimeterHit c = hits.get(i);
+            decoder.setID(c.getCellID());
+            
+            long[] neighbors = decoder.getNeighbourIDs(dLayer, dU, dV);
+            // loop over all neighboring cell Ids
+            for (int j=0; j<neighbors.length; ++j)
             {
-                if (h.getEnergy() >= threshold)
-                    addHit(h);
-                hitmap.remove(neighbors[j]);
+                CalorimeterHit h = hitmap.get(neighbors[j]);
+                // is the neighboring cell id hit?
+                // if so, does it meet or exceed threshold?
+                if (h != null)
+                {
+                    if (h.getEnergy() >= threshold)
+                        addHit(h);
+                    hitmap.remove(neighbors[j]);
+                }
             }
-         }
-      }
-      //        calculateDerivedQuantities();
-   }
-
-   /**
-    * Construct a NearestNeighborCluster. Note that the constructor actually performs the
-    * clustering, given a seed hit, without considering an energy threshold.
-    * @param decoder The CellID decoder appropriate for this collection of hits.
-    * @param hitmap The list of hit calorimeter cells available for clustering.
-    * @param hit The seed calorimeter hit for this cluster.
-    * @param key The key for the seed calorimeter hit.
-    */
-   public NearestNeighborCluster(CalorimeterIDDecoder decoder, Map<Long, CalorimeterHit> hitmap, CalorimeterHit hit, Long key, int dU, int dV, int dLayer)
-   {
-       this(decoder, hitmap, hit, key, dU, dV, dLayer, 0.0);
-   }
-   
-   /**
-    * String representation of this object.
-    * @return A String representation of this object
-    */
-   
-   public String toString()
-   {
-      return "NearestNeighborCluster with "+hits.size()+ " calorimeter hits";
-   }
+        }
+        //        calculateDerivedQuantities();
+    }
+    
+    /**
+     * Construct a NearestNeighborCluster. Note that the constructor actually performs the
+     * clustering, given a seed hit, without considering an energy threshold.
+     * @param decoder The CellID decoder appropriate for this collection of hits.
+     * @param hitmap The list of hit calorimeter cells available for clustering.
+     * @param hit The seed calorimeter hit for this cluster.
+     * @param key The key for the seed calorimeter hit.
+     */
+    public NearestNeighborCluster(CalorimeterIDDecoder decoder, Map<Long, CalorimeterHit> hitmap, CalorimeterHit hit, Long key, int dU, int dV, int dLayer)
+    {
+        this(decoder, hitmap, hit, key, dU, dV, dLayer, 0.0);
+    }
+    
+    /**
+     * String representation of this object.
+     * @return A String representation of this object
+     */
+    
+    public String toString()
+    {
+        return "NearestNeighborCluster with "+hits.size()+ " calorimeter hits";
+    }
 }

lcsim/src/org/lcsim/recon/cluster/nn
NearestNeighborClusterer.java 1.6 -> 1.7
diff -u -r1.6 -r1.7
--- NearestNeighborClusterer.java	8 Jul 2005 17:15:07 -0000	1.6
+++ NearestNeighborClusterer.java	18 Jul 2005 03:06:19 -0000	1.7
@@ -14,96 +14,81 @@
 import org.lcsim.util.Driver;
 
 /**
- * A simple driver which applies a nearest neighbor clustering algorithm
- * to calorimeter cell collections contained in the event.
- *
+ * Class to create a list of of Nearest Neighbor clusters
  * @author Norman A. Graf with additions of threshold code by Eric J. Benavidez ([log in to unmask])
  */
-public class NearestNeighborClusterer extends Driver
+public class NearestNeighborClusterer
 {
-   // the minimum number of cells to qualify as a cluster
-   private int _minNcells;
-   
-   // the neighborhood in u to search
-   private int _dU;
-   // the neighborhood in v to search
-   private int _dV;
-   // the neighborood in layers to search
-   private int _dLayer;
-   // energy threshold
-   private double _thresh;
-   // Create clusters class
-   private CreateNNClusters cnnc;
-   
-   /**
-    * Creates a new instance of NearestNeighborClusterer with a domain of (1,1,1)
-    * and no threshold.
-    * @param ncells The minimum number of cells required to constitute a cluster.
-    */
-   public NearestNeighborClusterer(int ncells)
-   {
-      this(1, 1, 1, ncells, 0);
-   }
-   
-   /**
-    * Creates a new instance of NearestNeighborClusterer
-    * @param dU  The extent in the U coordinate which defines a neighborhood.
-    * @param dV  The extent in the V coordinate which defines a neighborhood.
-    * @param dLayer  The extent in the layer which defines a neighborhood.
-    * @param ncells The minimum number of cells required to constitute a cluster.
-    * @param threshold The energy threshold that must be met or exceeded in order
-    *   to be considered in the cluster.
-    */
-   public NearestNeighborClusterer(int dU, int dV, int dLayer, int ncells,
-            double threshold)
-   {
-      _dU = dU;
-      _dV = dV;
-      _dLayer = dLayer;
-      _minNcells = ncells;
-      _thresh = threshold;
-      cnnc = new CreateNNClusters(_dU,_dV,_dLayer,_minNcells,_thresh);
-   }
-   
-   /**
-    * Creates a new NearestNeighborClusterer with no energy threshold applied.
-    * @param dU  The extent in the U coordinate which defines a neighborhood.
-    * @param dV  The extent in the V coordinate which defines a neighborhood.
-    * @param dLayer  The extent in the layer which defines a neighborhood.
-    * @param ncells The minimum number of cells required to constitute a cluster.
-    */
-   
-   public NearestNeighborClusterer(int dU, int dV, int dLayer, int ncells)
-   {
-       this(dU, dV, dLayer, ncells, 0);
-   }
-   
-   /**
-    * Process an event. Extract calorimeter cells from collections contained in the
-    * event, cluster the cells using a nearest-neighbor algorithm, and add these
-    * cluster containers back to the event.
-    *
-    * @param event
-    */
-   public void process(EventHeader event)
-   {
-      //First look for clusters in individual collections
-      
-      List<List<CalorimeterHit>> collections = event.get(CalorimeterHit.class);
-      for (List<CalorimeterHit> collection: collections)
-      {
-         CalorimeterIDDecoder decoder = (CalorimeterIDDecoder) event.getMetaData(collection).getIDDecoder();
-         List<BasicCluster> clusters = cnnc.findClusters(collection,decoder);
-         
-         String name = event.getMetaData(collection).getName();
-         if (clusters.size() > 0)
-             event.put(name+"NNClusters",clusters);
-      }
-   }
-   
+    // the minimum number of cells to qualify as a cluster
+    private int _minNcells;
+    
+    // the neighborhood in u to search
+    private int _dU;
+    // the neighborhood in v to search
+    private int _dV;
+    // the neighborood in layers to search
+    private int _dLayer;
+    // energy threshold
+    private double _thresh;
+    
+    /**
+     */
+    public NearestNeighborClusterer()
+    {
+        this(1, 1, 1, 1, 0.);
+    }
+    /**
+     */
+    public NearestNeighborClusterer(int dU, int dV, int dLayer, int ncells, double threshold)
+    {
+        _dU = dU;
+        _dV = dV;
+        _dLayer = dLayer;
+        _minNcells = ncells;
+        _thresh = threshold;
+    }
+    public void setGrid(int dU, int dV, int dLayer)
+    {
+        _dU = dU;
+        _dV = dV;
+        _dLayer = dLayer;
+    }
+    public void setMinNcells(int ncells)
+    {
+        _minNcells = ncells;
+    }
+    public void setThreshold(double threshold)
+    {
+        _thresh = threshold;
+    }
+    public List<BasicCluster> findClusters(List<CalorimeterHit> hitlist, CalorimeterIDDecoder decoder)
+    {
+        // create a map of cells keyed on their index
+        List<BasicCluster> clusters = new ArrayList();
+        Map<Long, CalorimeterHit> hitmap = new HashMap<Long, CalorimeterHit>();
+        for (CalorimeterHit hit : hitlist)
+        {
+            long id = hit.getCellID();
+            hitmap.put(id, hit);
+        }
+        while (!hitmap.isEmpty())
+        {
+            Long k = hitmap.keySet().iterator().next();
+            CalorimeterHit hit = hitmap.get(k);
+            // start a cluster, constructor will aggregate remaining hits unto itself
+            // NB : Must pass the threshold into the constructor, otherwise threshold
+            // will not be used.
+            NearestNeighborCluster nnclus = new NearestNeighborCluster(decoder, hitmap, hit, k, _dU, _dV, _dLayer, _thresh);
+            if(nnclus.getCalorimeterHits().size()>_minNcells)
+            {
+                clusters.add(nnclus);
+            }
+        }
+        return clusters;
+    }
+ 
    public String toString()
    {
       return "NearestNeighborClusterer "+_dU+" "+_dV+" "+_dLayer+" minimum of "+_minNcells+" cells";
-   }
-   
-}
+   }    
+}
\ No newline at end of file

lcsim/src/org/lcsim/recon/cluster/nn
CreateNNClusters.java removed after 1.1
diff -N CreateNNClusters.java
--- CreateNNClusters.java	8 Jul 2005 17:15:07 -0000	1.1
+++ /dev/null	1 Jan 1970 00:00:00 -0000
@@ -1,90 +0,0 @@
-package org.lcsim.recon.cluster.nn;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import org.lcsim.event.CalorimeterHit;
-import org.lcsim.event.EventHeader;
-import org.lcsim.event.SimCalorimeterHit;
-import org.lcsim.geometry.CalorimeterIDDecoder;
-import org.lcsim.recon.cluster.util.*;
-import org.lcsim.util.Driver;
-
-/**
- * Class to create a list of of Nearest Neighbor clusters
- * @author Norman A. Graf with additions of threshold code by Eric J. Benavidez ([log in to unmask])
- */
-public class CreateNNClusters 
-{
-   // the minimum number of cells to qualify as a cluster
-   private int _minNcells;
-   
-   // the neighborhood in u to search
-   private int _dU;
-   // the neighborhood in v to search
-   private int _dV;
-   // the neighborood in layers to search
-   private int _dLayer;
-   // energy threshold
-   private double _thresh;
-   
-	/**
-	 */
-	public CreateNNClusters()
-	{
-		this(1, 1, 1, 1, 0.);
-	}
-	/**
-	 */
-	public CreateNNClusters(int dU, int dV, int dLayer, int ncells, double threshold)
-	{
-		_dU = dU;
-		_dV = dV;
-		_dLayer = dLayer;
-		_minNcells = ncells;
-		_thresh = threshold;
-	}
-	public void setGrid(int dU, int dV, int dLayer)
-	{
-		_dU = dU;
-		_dV = dV;
-		_dLayer = dLayer;
-	}
-	public void setMinNcells(int ncells)
-	{
-		_minNcells = ncells;
-	}
-	public void setThreshold(double threshold)
-	{
-		_thresh = threshold;
-	}
-	public List<BasicCluster> findClusters(List<CalorimeterHit> hitlist, CalorimeterIDDecoder decoder)
-	{
-        // create a map of cells keyed on their index
-		List<BasicCluster> clusters = new ArrayList();
-        Map<Long, CalorimeterHit> hitmap = new HashMap<Long, CalorimeterHit>();
-        for (CalorimeterHit hit : hitlist)
-        {
-           long id = hit.getCellID();
-           hitmap.put(id, hit);
-        }
-        while (!hitmap.isEmpty())
-        {
-           Long k = hitmap.keySet().iterator().next();
-           CalorimeterHit hit = hitmap.get(k);
-            // start a cluster, constructor will aggregate remaining hits unto itself
-            // NB : Must pass the threshold into the constructor, otherwise threshold
-            // will not be used.
-           NearestNeighborCluster nnclus = new NearestNeighborCluster(decoder, hitmap, hit, k, _dU, _dV, _dLayer, _thresh);
-           if(nnclus.getCalorimeterHits().size()>_minNcells)
-           {
-              clusters.add(nnclus);
-           }
-        }
-		return clusters;
-    }
-   
-}

lcsim/src/org/lcsim/recon/cluster/util
BasicCluster.java 1.2 -> 1.3
diff -u -r1.2 -r1.3
--- BasicCluster.java	8 Jul 2005 17:15:08 -0000	1.2
+++ BasicCluster.java	18 Jul 2005 03:06:19 -0000	1.3
@@ -10,287 +10,287 @@
 
 /**
  * Default implementation of Cluster Interface for Simulation
- * 
+ *
  * @author cassell
  */
 public class BasicCluster implements Cluster
 {
-	protected List<CalorimeterHit> hits = new ArrayList<CalorimeterHit>();
-	protected List<Cluster> clusters = new ArrayList<Cluster>();
-	protected List<Subdetector> detectors = new ArrayList<Subdetector>();
-	public double raw_energy;
-	public double corrected_energy;
-	protected List<Double> subdetector_raw_energies = new ArrayList<Double>();
-	protected List<Double> subdetector_corrected_energies = new ArrayList<Double>();
-	protected List<Double> hit_energies = new ArrayList<Double>();
-	protected ClusterPropertyCalculator cluster_property_calculator = new DefaultClusterPropertyCalculator();
-	protected boolean needsPropertyCalculation = true;
-	protected double[] position;
-	protected double[] positionError;
-	protected double iphi;
-	protected double itheta;
-	protected double[] directionError;
-	protected double[] shapeParameters;
-
-	/** 
-	 * Add a CalorimeterHit to the cluster
-	 */
-	public void addHit(CalorimeterHit hit)
-	{
-		hits.add(hit);
-		raw_energy += hit.getEnergy();
-		/*
-		 Subdetector d = hit.getSubdetector();
-		 int detector_index = detectors.indexOf(d);
-		 if(detector_index <0)
-		 {
-		 detectors.add(d);
-		 detector_index = detectors.indexOf(d);
-		 subdetector_raw_energies.add(0.);
-		 subdetector_corrected_energies.add(0.);
-		 }
-		 double sampling_fraction = d.getSamplingFraction();
-		 */
-		int detector_index = 0;
-		double sampling_fraction = 1.;
-		if(subdetector_raw_energies.size() < 1)
-		{
-			subdetector_raw_energies.add(0.);
-			subdetector_corrected_energies.add(0.);
-		}
-		double hce = hit.getEnergy()/sampling_fraction;
-		corrected_energy += hce;
-		hit_energies.add(hce);
-		subdetector_raw_energies.set(detector_index,subdetector_raw_energies.get(detector_index) + hit.getEnergy());
-		subdetector_corrected_energies.set(detector_index,subdetector_corrected_energies.get(detector_index) + hce);
-		needsPropertyCalculation = true;
-	}
-
-	/** 
-	 * Remove a CalorimeterHit from the cluster
-	 */
-	public void removeHit(CalorimeterHit hit)
-	{
-		int indx = hits.indexOf(hit);
-		hits.remove(hit);
-		raw_energy -= hit.getEnergy();
-		/*
-		 Subdetector d = hit.getSubdetector();
-		 int detector_index = detectors.indexOf(d);
-		 if(detector_index <0)
-		 {
-		 detectors.add(d);
-		 detector_index = detectors.indexOf(d);
-		 subdetector_raw_energies.add(0.);
-		 subdetector_corrected_energies.add(0.);
-		 }
-		 double sampling_fraction = d.getSamplingFraction();
-		 */
-		int detector_index = 0;
-		double sampling_fraction = 1.;
-		double hce = hit.getEnergy()/sampling_fraction;
-		corrected_energy -= hce;
-		hit_energies.remove(indx);
-		subdetector_raw_energies.set(detector_index,subdetector_raw_energies.get(detector_index) - hit.getEnergy());
-		subdetector_corrected_energies.set(detector_index,subdetector_corrected_energies.get(detector_index) - hce);
-		needsPropertyCalculation = true;
-	}
-	/** 
-	 * Add a Cluster to the cluster
-	 */
-	public void addCluster(Cluster cluster)
-    {
-       clusters.add(cluster);
-       List<CalorimeterHit> chits = cluster.getCalorimeterHits();
-   	   if(chits.size() > 0)
-	   {
-		   for(int i=0;i<chits.size();i++)
-		   {
-			   addHit(chits.get(i));
-		   }
-		   needsPropertyCalculation = true;
-	   }
-	   else
-	   {
-		   corrected_energy += cluster.getEnergy();
-		   double[] sde = cluster.getSubdetectorEnergies();
-		   for(int i=0;i<sde.length;i++)
-		   {
-			   subdetector_corrected_energies.set(i,subdetector_corrected_energies.get(i) + sde[i]);
-		   }
-	   }
-    }
-   
-	/** 
-	 * Return the hits comprising the cluster as per interface
-	 */
-	public List<CalorimeterHit> getCalorimeterHits()
-    {
-       return hits;
-    }
-
-	/** 
-	 * Return the clusters comprising the cluster as per interface
-	 */
-	public List<Cluster> getClusters()
-    {
-       return clusters;
-    }
-
-	/** 
-	 * Return the corrected Energy of the cluster as per interface
-	 */
-	public double getEnergy()
-	{
-		return corrected_energy;
-	}
-
-	/** 
-	 * Return the corrected energy contribution of each hit 
-	 * comprising the cluster as per interface
-	 */
-	public double[] getHitContributions()
-    {
-		double[] earray = new double[hit_energies.size()];
-		for(int i=0;i<hit_energies.size();i++)
-		{
-			earray[i] = hit_energies.get(i);
-		}
-		return earray;
-    }
-
-	/** 
-	 * Return the phi direction of the cluster as per interface
-	 */
-	public double getIPhi()
-    {
-	   if(needsPropertyCalculation)
-	   {
-		   calculateProperties();
-	   }
-       return iphi;
-    }
-
-	/** 
-	 * Return the theta direction of the cluster as per interface
-	 */
-	public double getITheta()
-    {
-	   if(needsPropertyCalculation)
-	   {
-		   calculateProperties();
-	   }
-	   return itheta;
-    }
-
-	/** 
-	 * Return the direction error of the cluster as per interface
-	 */
-	public double[] getDirectionError()
-	{
-		if(needsPropertyCalculation)
-		{
-			calculateProperties();
-		}
-		return directionError;
-	}
-
-	/** 
-	 * Return the position of the cluster as per interface
-	 */
-	public double[] getPosition()
-    {
-		if(needsPropertyCalculation)
-		{
-			calculateProperties();
-		}
-		return position;
-	}
-
-	/** 
-	 * Return the position error of the cluster as per interface
-	 */
-	public double[] getPositionError()
-    {
-	   if(needsPropertyCalculation)
-	   {
-		   calculateProperties();
-	   }
-	   return positionError;
-    }
-
-	/** 
-	 * Return the shape parameters of the cluster as per interface
-	 */
-	public double[] getShape()
-    {
-	   if(needsPropertyCalculation)
-	   {
-		   calculateProperties();
-	   }
-	   return shapeParameters;
-    }
-
-	/** 
-	 * Return the subdetector energy contributions
-	 *  of the cluster as per interface
-	 */
-	public double[] getSubdetectorEnergies()
-    {
-		double[] sdearray = new double[subdetector_corrected_energies.size()];
-		for(int i=0;i<subdetector_corrected_energies.size();i++)
-		{
-			sdearray[i] = subdetector_corrected_energies.get(i);
-		}
-		return sdearray;
-	}
-
-	/** 
-	 * Return a bit mask defining the type of cluster as per interface
-	 */
-	public int getType()
-    {
-      return 0;
-    }
-
-	/**
-	 * Return the sum of the raw energies from the hits in the cluster
-	 */
-	public double getRawEnergy()
-	{
-		return raw_energy;
-	}
-
-	/**
-	 * Allow for recalculation of cluster properties, or 
-	 * prevent recalculation after adding to cluster
-	 */
-	public void setNeedsPropertyCalculation(boolean tf)
-	{
-		needsPropertyCalculation = tf;
-	}
-
-	/**
-	 * Override the default ClusterPropertyCalculator
-	 */
-	public void setPropertyCalculator(ClusterPropertyCalculator cpc)
-	{
-		cluster_property_calculator = cpc;
-	}
-
-	/**
-	 * Calculate the cluster properties from the hits
-	 */
-	public void calculateProperties()
-	{
-		cluster_property_calculator.calculateProperties(hits);
-		position = cluster_property_calculator.getPosition();
-		positionError = cluster_property_calculator.getPositionError();
-		iphi = cluster_property_calculator.getIPhi();
-		itheta = cluster_property_calculator.getITheta();
-		directionError = cluster_property_calculator.getDirectionError();
-		shapeParameters = cluster_property_calculator.getShapeParameters();
-		needsPropertyCalculation = false;
-	}
-		
+    protected List<CalorimeterHit> hits = new ArrayList<CalorimeterHit>();
+    protected List<Cluster> clusters = new ArrayList<Cluster>();
+    protected List<Subdetector> detectors = new ArrayList<Subdetector>();
+    public double raw_energy;
+    public double corrected_energy;
+    protected List<Double> subdetector_raw_energies = new ArrayList<Double>();
+    protected List<Double> subdetector_corrected_energies = new ArrayList<Double>();
+    protected List<Double> hit_energies = new ArrayList<Double>();
+    protected ClusterPropertyCalculator cluster_property_calculator = new DefaultClusterPropertyCalculator();
+    protected boolean needsPropertyCalculation = true;
+    protected double[] position;
+    protected double[] positionError;
+    protected double iphi;
+    protected double itheta;
+    protected double[] directionError;
+    protected double[] shapeParameters;
+    
+    /**
+     * Add a CalorimeterHit to the cluster
+     */
+    public void addHit(CalorimeterHit hit)
+    {
+        hits.add(hit);
+        raw_energy += hit.getEnergy();
+                /*
+                 Subdetector d = hit.getSubdetector();
+                 int detector_index = detectors.indexOf(d);
+                 if(detector_index <0)
+                 {
+                 detectors.add(d);
+                 detector_index = detectors.indexOf(d);
+                 subdetector_raw_energies.add(0.);
+                 subdetector_corrected_energies.add(0.);
+                 }
+                 double sampling_fraction = d.getSamplingFraction();
+                 */
+        int detector_index = 0;
+        double sampling_fraction = 1.;
+        if(subdetector_raw_energies.size() < 1)
+        {
+            subdetector_raw_energies.add(0.);
+            subdetector_corrected_energies.add(0.);
+        }
+        double hce = hit.getEnergy()/sampling_fraction;
+        corrected_energy += hce;
+        hit_energies.add(hce);
+        subdetector_raw_energies.set(detector_index,subdetector_raw_energies.get(detector_index) + hit.getEnergy());
+        subdetector_corrected_energies.set(detector_index,subdetector_corrected_energies.get(detector_index) + hce);
+        needsPropertyCalculation = true;
+    }
+    
+    /**
+     * Remove a CalorimeterHit from the cluster
+     */
+    public void removeHit(CalorimeterHit hit)
+    {
+        int indx = hits.indexOf(hit);
+        hits.remove(hit);
+        raw_energy -= hit.getEnergy();
+                /*
+                 Subdetector d = hit.getSubdetector();
+                 int detector_index = detectors.indexOf(d);
+                 if(detector_index <0)
+                 {
+                 detectors.add(d);
+                 detector_index = detectors.indexOf(d);
+                 subdetector_raw_energies.add(0.);
+                 subdetector_corrected_energies.add(0.);
+                 }
+                 double sampling_fraction = d.getSamplingFraction();
+                 */
+        int detector_index = 0;
+        double sampling_fraction = 1.;
+        double hce = hit.getEnergy()/sampling_fraction;
+        corrected_energy -= hce;
+        hit_energies.remove(indx);
+        subdetector_raw_energies.set(detector_index,subdetector_raw_energies.get(detector_index) - hit.getEnergy());
+        subdetector_corrected_energies.set(detector_index,subdetector_corrected_energies.get(detector_index) - hce);
+        needsPropertyCalculation = true;
+    }
+    /**
+     * Add a Cluster to the cluster
+     */
+    public void addCluster(Cluster cluster)
+    {
+        clusters.add(cluster);
+        List<CalorimeterHit> chits = cluster.getCalorimeterHits();
+        if(chits.size() > 0)
+        {
+            for(int i=0;i<chits.size();i++)
+            {
+                addHit(chits.get(i));
+            }
+            needsPropertyCalculation = true;
+        }
+        else
+        {
+            corrected_energy += cluster.getEnergy();
+            double[] sde = cluster.getSubdetectorEnergies();
+            for(int i=0;i<sde.length;i++)
+            {
+                subdetector_corrected_energies.set(i,subdetector_corrected_energies.get(i) + sde[i]);
+            }
+        }
+    }
+    
+    /**
+     * Return the hits comprising the cluster as per interface
+     */
+    public List<CalorimeterHit> getCalorimeterHits()
+    {
+        return hits;
+    }
+    
+    /**
+     * Return the clusters comprising the cluster as per interface
+     */
+    public List<Cluster> getClusters()
+    {
+        return clusters;
+    }
+    
+    /**
+     * Return the corrected Energy of the cluster as per interface
+     */
+    public double getEnergy()
+    {
+        return corrected_energy;
+    }
+    
+    /**
+     * Return the corrected energy contribution of each hit
+     * comprising the cluster as per interface
+     */
+    public double[] getHitContributions()
+    {
+        double[] earray = new double[hit_energies.size()];
+        for(int i=0;i<hit_energies.size();i++)
+        {
+            earray[i] = hit_energies.get(i);
+        }
+        return earray;
+    }
+    
+    /**
+     * Return the phi direction of the cluster as per interface
+     */
+    public double getIPhi()
+    {
+        if(needsPropertyCalculation)
+        {
+            calculateProperties();
+        }
+        return iphi;
+    }
+    
+    /**
+     * Return the theta direction of the cluster as per interface
+     */
+    public double getITheta()
+    {
+        if(needsPropertyCalculation)
+        {
+            calculateProperties();
+        }
+        return itheta;
+    }
+    
+    /**
+     * Return the direction error of the cluster as per interface
+     */
+    public double[] getDirectionError()
+    {
+        if(needsPropertyCalculation)
+        {
+            calculateProperties();
+        }
+        return directionError;
+    }
+    
+    /**
+     * Return the position of the cluster as per interface
+     */
+    public double[] getPosition()
+    {
+        if(needsPropertyCalculation)
+        {
+            calculateProperties();
+        }
+        return position;
+    }
+    
+    /**
+     * Return the position error of the cluster as per interface
+     */
+    public double[] getPositionError()
+    {
+        if(needsPropertyCalculation)
+        {
+            calculateProperties();
+        }
+        return positionError;
+    }
+    
+    /**
+     * Return the shape parameters of the cluster as per interface
+     */
+    public double[] getShape()
+    {
+        if(needsPropertyCalculation)
+        {
+            calculateProperties();
+        }
+        return shapeParameters;
+    }
+    
+    /**
+     * Return the subdetector energy contributions
+     *  of the cluster as per interface
+     */
+    public double[] getSubdetectorEnergies()
+    {
+        double[] sdearray = new double[subdetector_corrected_energies.size()];
+        for(int i=0;i<subdetector_corrected_energies.size();i++)
+        {
+            sdearray[i] = subdetector_corrected_energies.get(i);
+        }
+        return sdearray;
+    }
+    
+    /**
+     * Return a bit mask defining the type of cluster as per interface
+     */
+    public int getType()
+    {
+        return 0;
+    }
+    
+    /**
+     * Return the sum of the raw energies from the hits in the cluster
+     */
+    public double getRawEnergy()
+    {
+        return raw_energy;
+    }
+    
+    /**
+     * Allow for recalculation of cluster properties, or
+     * prevent recalculation after adding to cluster
+     */
+    public void setNeedsPropertyCalculation(boolean tf)
+    {
+        needsPropertyCalculation = tf;
+    }
+    
+    /**
+     * Override the default ClusterPropertyCalculator
+     */
+    public void setPropertyCalculator(ClusterPropertyCalculator cpc)
+    {
+        cluster_property_calculator = cpc;
+    }
+    
+    /**
+     * Calculate the cluster properties from the hits
+     */
+    public void calculateProperties()
+    {
+        cluster_property_calculator.calculateProperties(hits);
+        position = cluster_property_calculator.getPosition();
+        positionError = cluster_property_calculator.getPositionError();
+        iphi = cluster_property_calculator.getIPhi();
+        itheta = cluster_property_calculator.getITheta();
+        directionError = cluster_property_calculator.getDirectionError();
+        shapeParameters = cluster_property_calculator.getShapeParameters();
+        needsPropertyCalculation = false;
+    }
+    
 }

lcsim/src/org/lcsim/recon/cluster/util
TensorClusterPropertyCalculator.java 1.2 -> 1.3
diff -u -r1.2 -r1.3
--- TensorClusterPropertyCalculator.java	8 Jul 2005 17:15:08 -0000	1.2
+++ TensorClusterPropertyCalculator.java	18 Jul 2005 03:06:19 -0000	1.3
@@ -9,279 +9,280 @@
 
 /**
  * Implementation of ClusterPropertyCalculator Interface using
- * inertia Tensor calculation to derive parameters 
- * 
+ * inertia Tensor calculation to derive parameters
+ *
  * @author cassell
  */
 public class TensorClusterPropertyCalculator implements ClusterPropertyCalculator
 {
-	protected double[] position;
-	protected double[] positionError;
-	protected double iphi;
-	protected double itheta;
-	protected double[] directionError;
-	protected double[] shapeParameters;
-	protected double[] mm_NE;
-                             protected double[] mm_CE;
-                             protected double[][] mm_PA;
-
-	/** 
-	 * Calculate the cluster properties from the hits
-	 */
-	public TensorClusterPropertyCalculator()
-	{
-		position = new double[3];
-		positionError = new double[6];
-		iphi = 0.;
-		itheta = 0.;
-		directionError = new double[6];
-		shapeParameters = new double[6];
-	}
-	public void calculateProperties(List<CalorimeterHit> hits)
-	{
-		mm_NE = new double[3];
-		mm_CE = new double[3];
-		mm_PA = new double[3][3]; 
-		for(int i=0;i<3;++i)
-		{
-			mm_NE[i] = 0.;
-			mm_CE[i] = 0.;
-			for(int j=0;j<3;++j){mm_PA[i][j]= 0.;}
-		}
-		double Etot = 0.0;
-		double Exx = 0.0;
-		double Eyy = 0.0;
-		double Ezz = 0.0;
-		double Exy = 0.0;
-		double Eyz = 0.0;
-		double Exz = 0.0;
-		double CEx = 0.0;
-		double CEy = 0.0;
-		double CEz = 0.0;
-		double CEr = 0.0;
-		double E1 = 0.0;
-		double E2 = 0.0;
-		double E3 = 0.0;
-		double NE1 = 0.0;
-		double NE2 = 0.0;
-		double NE3 = 0.0;
-		double Tr = 0.0;
-		double M = 0.0;
-		double Det = 0.0;
-		int nhits = hits.size();
-		for(int i=0;i<hits.size();i++)
-		{
-			CalorimeterHit hit = hits.get(i);
-		//	CalorimeterIDDecoder decoder = hit.getDecoder();
-		//	decoder.setID(hit.getCellID());
-		//	double[] pos = new double[3];
-		//	pos[0] = decoder.getX();
-		//	pos[1] = decoder.getY();
-		//	pos[2] = decoder.getZ();
-			double[] pos = hit.getPosition();
-		//	Subdetector d = hit.getSubdetector();
-		//	double sampling_fraction = d.getSamplingFraction();
-			double sampling_fraction = 1.;
-			double E = hit.getEnergy()/sampling_fraction;
-			Etot += E;
-			CEx += E*pos[0];
-			CEy += E*pos[1];
-			CEz += E*pos[2];
-			Exx += E*(pos[1]*pos[1] + pos[2]*pos[2]);
-			Eyy += E*(pos[0]*pos[0] + pos[2]*pos[2]);
-			Ezz += E*(pos[1]*pos[1] + pos[0]*pos[0]);
-			Exy -= E*pos[0]*pos[1];
-			Eyz -= E*pos[1]*pos[2];
-			Exz -= E*pos[0]*pos[2];
-		}
-		CEx = CEx/Etot;
-		CEy = CEy/Etot;
-		CEz = CEz/Etot;
-		double CErSq = CEx*CEx + CEy*CEy + CEz*CEz;
-		CEr = Math.sqrt(CErSq);
-		// now go to center of energy coords.
-		if (nhits > 3 )
-		{
-			Exx = Exx - Etot*(CErSq - CEx*CEx);
-			Eyy = Eyy - Etot*(CErSq - CEy*CEy);
-			Ezz = Ezz - Etot*(CErSq - CEz*CEz);
-			Exy = Exy + Etot*CEx*CEy;
-			Eyz = Eyz + Etot*CEy*CEz;
-			Exz = Exz + Etot*CEz*CEx;
-
-	//
-			Tr = Exx + Eyy + Ezz;
-			double Dxx = Eyy*Ezz - Eyz*Eyz;
-			double Dyy = Ezz*Exx - Exz*Exz;
-			double Dzz = Exx*Eyy - Exy*Exy;
-			M = Dxx + Dyy + Dzz;
-			double Dxy = Exy*Ezz - Exz*Eyz;
-			double Dxz = Exy*Eyz - Exz*Eyy;
-			Det = Exx*Dxx - Exy*Dxy + Exz*Dxz;
-			double xt = Tr*Tr - 3*M;
-			double sqrtxt = Math.sqrt(xt);
-	// eqn to solve for eigenvalues is x**3 - x**2*Tr + x*M - Det = 0
-	// crosses y axis at -Det and inflection points are 
-				
-			double mE1 = 0.;
-			double mE2 = 0.;
-			double mE3 = 0.;
-			double a = (3*M - Tr*Tr)/3.;
-			double b = (-2*Tr*Tr*Tr + 9*Tr*M -27*Det)/27.;
-			double test = b*b/4. + a*a*a/27.;
-			if(test >= 0.01)
-			{
-				System.out.println("AbstractCluster: Only 1 real root!!!");
-				System.out.println("  nhits = " + nhits + "\n");
-				System.out.println(" a,b,test = " + a + " " + b + " " + test + "\n");
-			}
-			else
-			{
-				double temp;
-				if(test >= 0.)temp = 1.;
-				else temp = Math.sqrt(b*b*27./(-a*a*a*4.));
-				if(b > 0.)temp = -temp;
-				double phi = Math.acos(temp);
-				double temp1 = 2.*Math.sqrt(-a/3.);
-				mE1 = Tr/3. + 2.*Math.sqrt(-a/3.)*Math.cos(phi/3.);
-				mE2 = Tr/3. + 2.*Math.sqrt(-a/3.)*Math.cos(phi/3. + 2.*Math.PI/3.);
-				mE3 = Tr/3. + 2.*Math.sqrt(-a/3.)*Math.cos(phi/3. + 4.*Math.PI/3.);
-			}
-			if(mE1 < mE2)
-			{
-				if(mE1 < mE3)
-				{
-					E1 = mE1;
-					if(mE2 < mE3)
-					{
-						E2 = mE2;
-						E3 = mE3;
-					}
-					else
-					{
-						E2 = mE3;
-						E3 = mE2;
-					}
-				}
-				else
-				{
-					E1 = mE3;
-					E2 = mE1;
-					E3 = mE2;
-				}
-			}
-			else
-			{
-				if(mE2 < mE3)
-				{
-					E1 = mE2;
-					if(mE1 < mE3)
-					{
-						E2 = mE1;
-						E3 = mE3;
-					}
-					else
-					{
-						E2 = mE3;
-						E3 = mE1;
-					}
-				}
-				else
-				{
-					E1 = mE3;
-					E2 = mE2;
-					E3 = mE1;
-				}
-			}
-			
-			NE1 = E1/Etot;
-			NE2 = E2/Etot;
-			NE3 = E3/Etot;
-			double[] EV = new double[3];
-			EV[0] = E1;
-			EV[1] = E2;
-			EV[2] = E3;
-	// Now calculate principal axes
-			for( int i = 0 ; i < 3 ; i++ )
-			{
-				double[] C = new double[3];
-				C[0] = 1.0;
-				C[2] = (Exy*Exy + (Eyy - EV[i])*(EV[i] - Exx))/
-				((Eyy - EV[i])*Exz - Eyz*Exy);
-				C[1] = (EV[i] - Exx - Exz*C[2])/Exy;
-				double norm = Math.sqrt(C[0]*C[0] + C[1]*C[1] + C[2]*C[2]);
-				mm_PA[i][0] = C[0]/norm;
-				mm_PA[i][1] = C[1]/norm;
-				mm_PA[i][2] = C[2]/norm;
-			}
-		}
-		mm_NE[0] = NE1;
-		mm_NE[1] = NE2;
-		mm_NE[2] = NE3;
-		mm_CE[0] = CEx;
-		mm_CE[1] = CEy;
-		mm_CE[2] = CEz;
-		for(int i=0;i<6;i++)
-		{
-			positionError[i] = 0.;
-			directionError[i] = 0.;
- 			shapeParameters[i] = 0.;
-		}
-		for(int i=0;i<3;i++)
-		{
-			position[i] = mm_CE[i];
-			shapeParameters[i] = mm_NE[i];
-		}
-		if(nhits > 3)
-		{
-			double dr = Math.sqrt(  (position[0]+mm_PA[0][0])*(position[0]+mm_PA[0][0]) +
-									(position[1]+mm_PA[0][1])*(position[1]+mm_PA[0][1]) +
-									(position[2]+mm_PA[0][2])*(position[2]+mm_PA[0][2]) ) -
-					    Math.sqrt(	(position[0])*(position[0]) +
-									(position[1])*(position[1]) +
-									(position[2])*(position[2]) ) ;
-			double sign = 1.;
-			if(dr < 0.)sign = -1.;
-			itheta = Math.acos(sign*mm_PA[0][2]);
-			iphi = Math.atan2(sign*mm_PA[0][1],sign*mm_PA[0][0]);
-		}
-		else
-		{
-			itheta = 999.;
-			iphi = 999.;
-		}
-	}
-	public double[] getPosition()
-	{
-		return position;
-	}
-	public double[] getPositionError()
-	{
-		return positionError;
-	}
-	public double getIPhi()
-	{
-		return iphi;
-	}
-	public double getITheta()
-	{
-		return itheta;
-	}
-	public double[] getDirectionError()
-	{
-		return directionError;
-	}
-	public double[] getShapeParameters()
-	{
-		return shapeParameters;
-	}
-	public double[] getNormalizedEigenvalues()
-	{
-		return mm_NE;
-	}
-	public double[][] getPrincipleAxis()
-	{
-		return mm_PA;
-	}
-		
+    protected double[] position;
+    protected double[] positionError;
+    protected double iphi;
+    protected double itheta;
+    protected double[] directionError;
+    protected double[] shapeParameters;
+    protected double[] mm_NE;
+    protected double[] mm_CE;
+    protected double[][] mm_PA;
+    
+    /**
+     * Calculate the cluster properties from the hits
+     */
+    public TensorClusterPropertyCalculator()
+    {
+        position = new double[3];
+        positionError = new double[6];
+        iphi = 0.;
+        itheta = 0.;
+        directionError = new double[6];
+        shapeParameters = new double[6];
+    }
+    public void calculateProperties(List<CalorimeterHit> hits)
+    {
+        mm_NE = new double[3];
+        mm_CE = new double[3];
+        mm_PA = new double[3][3];
+        for(int i=0;i<3;++i)
+        {
+            mm_NE[i] = 0.;
+            mm_CE[i] = 0.;
+            for(int j=0;j<3;++j)
+            {mm_PA[i][j]= 0.;}
+        }
+        double Etot = 0.0;
+        double Exx = 0.0;
+        double Eyy = 0.0;
+        double Ezz = 0.0;
+        double Exy = 0.0;
+        double Eyz = 0.0;
+        double Exz = 0.0;
+        double CEx = 0.0;
+        double CEy = 0.0;
+        double CEz = 0.0;
+        double CEr = 0.0;
+        double E1 = 0.0;
+        double E2 = 0.0;
+        double E3 = 0.0;
+        double NE1 = 0.0;
+        double NE2 = 0.0;
+        double NE3 = 0.0;
+        double Tr = 0.0;
+        double M = 0.0;
+        double Det = 0.0;
+        int nhits = hits.size();
+        for(int i=0;i<hits.size();i++)
+        {
+            CalorimeterHit hit = hits.get(i);
+            //	CalorimeterIDDecoder decoder = hit.getDecoder();
+            //	decoder.setID(hit.getCellID());
+            //	double[] pos = new double[3];
+            //	pos[0] = decoder.getX();
+            //	pos[1] = decoder.getY();
+            //	pos[2] = decoder.getZ();
+            double[] pos = hit.getPosition();
+            //	Subdetector d = hit.getSubdetector();
+            //	double sampling_fraction = d.getSamplingFraction();
+            double sampling_fraction = 1.;
+            double E = hit.getEnergy()/sampling_fraction;
+            Etot += E;
+            CEx += E*pos[0];
+            CEy += E*pos[1];
+            CEz += E*pos[2];
+            Exx += E*(pos[1]*pos[1] + pos[2]*pos[2]);
+            Eyy += E*(pos[0]*pos[0] + pos[2]*pos[2]);
+            Ezz += E*(pos[1]*pos[1] + pos[0]*pos[0]);
+            Exy -= E*pos[0]*pos[1];
+            Eyz -= E*pos[1]*pos[2];
+            Exz -= E*pos[0]*pos[2];
+        }
+        CEx = CEx/Etot;
+        CEy = CEy/Etot;
+        CEz = CEz/Etot;
+        double CErSq = CEx*CEx + CEy*CEy + CEz*CEz;
+        CEr = Math.sqrt(CErSq);
+        // now go to center of energy coords.
+        if (nhits > 3 )
+        {
+            Exx = Exx - Etot*(CErSq - CEx*CEx);
+            Eyy = Eyy - Etot*(CErSq - CEy*CEy);
+            Ezz = Ezz - Etot*(CErSq - CEz*CEz);
+            Exy = Exy + Etot*CEx*CEy;
+            Eyz = Eyz + Etot*CEy*CEz;
+            Exz = Exz + Etot*CEz*CEx;
+            
+            //
+            Tr = Exx + Eyy + Ezz;
+            double Dxx = Eyy*Ezz - Eyz*Eyz;
+            double Dyy = Ezz*Exx - Exz*Exz;
+            double Dzz = Exx*Eyy - Exy*Exy;
+            M = Dxx + Dyy + Dzz;
+            double Dxy = Exy*Ezz - Exz*Eyz;
+            double Dxz = Exy*Eyz - Exz*Eyy;
+            Det = Exx*Dxx - Exy*Dxy + Exz*Dxz;
+            double xt = Tr*Tr - 3*M;
+            double sqrtxt = Math.sqrt(xt);
+            // eqn to solve for eigenvalues is x**3 - x**2*Tr + x*M - Det = 0
+            // crosses y axis at -Det and inflection points are
+            
+            double mE1 = 0.;
+            double mE2 = 0.;
+            double mE3 = 0.;
+            double a = (3*M - Tr*Tr)/3.;
+            double b = (-2*Tr*Tr*Tr + 9*Tr*M -27*Det)/27.;
+            double test = b*b/4. + a*a*a/27.;
+            if(test >= 0.01)
+            {
+                System.out.println("AbstractCluster: Only 1 real root!!!");
+                System.out.println("  nhits = " + nhits + "\n");
+                System.out.println(" a,b,test = " + a + " " + b + " " + test + "\n");
+            }
+            else
+            {
+                double temp;
+                if(test >= 0.)temp = 1.;
+                else temp = Math.sqrt(b*b*27./(-a*a*a*4.));
+                if(b > 0.)temp = -temp;
+                double phi = Math.acos(temp);
+                double temp1 = 2.*Math.sqrt(-a/3.);
+                mE1 = Tr/3. + 2.*Math.sqrt(-a/3.)*Math.cos(phi/3.);
+                mE2 = Tr/3. + 2.*Math.sqrt(-a/3.)*Math.cos(phi/3. + 2.*Math.PI/3.);
+                mE3 = Tr/3. + 2.*Math.sqrt(-a/3.)*Math.cos(phi/3. + 4.*Math.PI/3.);
+            }
+            if(mE1 < mE2)
+            {
+                if(mE1 < mE3)
+                {
+                    E1 = mE1;
+                    if(mE2 < mE3)
+                    {
+                        E2 = mE2;
+                        E3 = mE3;
+                    }
+                    else
+                    {
+                        E2 = mE3;
+                        E3 = mE2;
+                    }
+                }
+                else
+                {
+                    E1 = mE3;
+                    E2 = mE1;
+                    E3 = mE2;
+                }
+            }
+            else
+            {
+                if(mE2 < mE3)
+                {
+                    E1 = mE2;
+                    if(mE1 < mE3)
+                    {
+                        E2 = mE1;
+                        E3 = mE3;
+                    }
+                    else
+                    {
+                        E2 = mE3;
+                        E3 = mE1;
+                    }
+                }
+                else
+                {
+                    E1 = mE3;
+                    E2 = mE2;
+                    E3 = mE1;
+                }
+            }
+            
+            NE1 = E1/Etot;
+            NE2 = E2/Etot;
+            NE3 = E3/Etot;
+            double[] EV = new double[3];
+            EV[0] = E1;
+            EV[1] = E2;
+            EV[2] = E3;
+            // Now calculate principal axes
+            for( int i = 0 ; i < 3 ; i++ )
+            {
+                double[] C = new double[3];
+                C[0] = 1.0;
+                C[2] = (Exy*Exy + (Eyy - EV[i])*(EV[i] - Exx))/
+                        ((Eyy - EV[i])*Exz - Eyz*Exy);
+                C[1] = (EV[i] - Exx - Exz*C[2])/Exy;
+                double norm = Math.sqrt(C[0]*C[0] + C[1]*C[1] + C[2]*C[2]);
+                mm_PA[i][0] = C[0]/norm;
+                mm_PA[i][1] = C[1]/norm;
+                mm_PA[i][2] = C[2]/norm;
+            }
+        }
+        mm_NE[0] = NE1;
+        mm_NE[1] = NE2;
+        mm_NE[2] = NE3;
+        mm_CE[0] = CEx;
+        mm_CE[1] = CEy;
+        mm_CE[2] = CEz;
+        for(int i=0;i<6;i++)
+        {
+            positionError[i] = 0.;
+            directionError[i] = 0.;
+            shapeParameters[i] = 0.;
+        }
+        for(int i=0;i<3;i++)
+        {
+            position[i] = mm_CE[i];
+            shapeParameters[i] = mm_NE[i];
+        }
+        if(nhits > 3)
+        {
+            double dr = Math.sqrt(  (position[0]+mm_PA[0][0])*(position[0]+mm_PA[0][0]) +
+                    (position[1]+mm_PA[0][1])*(position[1]+mm_PA[0][1]) +
+                    (position[2]+mm_PA[0][2])*(position[2]+mm_PA[0][2]) ) -
+                    Math.sqrt(	(position[0])*(position[0]) +
+                    (position[1])*(position[1]) +
+                    (position[2])*(position[2]) ) ;
+            double sign = 1.;
+            if(dr < 0.)sign = -1.;
+            itheta = Math.acos(sign*mm_PA[0][2]);
+            iphi = Math.atan2(sign*mm_PA[0][1],sign*mm_PA[0][0]);
+        }
+        else
+        {
+            itheta = 999.;
+            iphi = 999.;
+        }
+    }
+    public double[] getPosition()
+    {
+        return position;
+    }
+    public double[] getPositionError()
+    {
+        return positionError;
+    }
+    public double getIPhi()
+    {
+        return iphi;
+    }
+    public double getITheta()
+    {
+        return itheta;
+    }
+    public double[] getDirectionError()
+    {
+        return directionError;
+    }
+    public double[] getShapeParameters()
+    {
+        return shapeParameters;
+    }
+    public double[] getNormalizedEigenvalues()
+    {
+        return mm_NE;
+    }
+    public double[][] getPrincipleAxis()
+    {
+        return mm_PA;
+    }
+    
 }

lcsim/src/org/lcsim/recon/cluster/util
FCClusterPropertyCalculator.java removed after 1.1
diff -N FCClusterPropertyCalculator.java
--- FCClusterPropertyCalculator.java	8 Jul 2005 17:15:08 -0000	1.1
+++ /dev/null	1 Jan 1970 00:00:00 -0000
@@ -1,330 +0,0 @@
-package org.lcsim.recon.cluster.util;
-
-import java.util.List;
-import org.lcsim.spacegeom.PrincipalAxesLineFitter;
-import org.lcsim.event.CalorimeterHit;
-import org.lcsim.geometry.CalorimeterIDDecoder;
-import org.lcsim.util.fourvec.Lorentz4Vector;
-import org.lcsim.util.fourvec.Momentum4Vector;
-
-/**
- * A class encapsulating the behavior of a calorimeter cluster.
- *
- * @author Norman A. Graf
- * @version 1.0
- */
-public class FCClusterPropertyCalculator implements ClusterPropertyCalculator
-{
-    private CalorimeterIDDecoder _decoder;
-    private Lorentz4Vector _vec;
-    // second moment of the cluster
-    private double _width;
-    private double[] _layerEnergy;
-    private double _clusterEnergy;
-    private double[] _layerWidth;
-    private double[] _centroid;
-    private double[] _directionCosines;
-    private double _samplingFraction;
-    private CalorimeterHit _hottestCell;
-    private double _highestCellEnergy;
-    private boolean _isEndCap;
-    private boolean _isNorth;
-    private double _chisq = 99999.;   
-	private int layers;
-	private double _itheta;
-	private double _iphi;
-    
-    /**
-     * Fully qualified constructor
-     *
-     * @param   decoder  The CalorimeterIDDecoder used for indexing
-     * @param   vec   The Lorentz four-vector
-     * @param   members  A Vector of CalorimeterHits
-     * @param   layers  The number of layers in the Calorimeter
-     * @param   samplingFraction The conversion from measured to deposited energy
-     */
-	public FCClusterPropertyCalculator(CalorimeterIDDecoder decoder)
-	{
-		_decoder = decoder;
-		layers = 64;
-	}
-	public void calculateProperties(List<CalorimeterHit> hits)
-	{
-        _vec = calculateVec(hits);
-        _layerEnergy = new double[layers];
-        _layerWidth = new double[layers];
-        // the array of cell (x,y,z) coordinates
-        double[][] points = new double[3][hits.size()];
-        int npoints=0;
-		_highestCellEnergy = 0.;
-        
-        for(CalorimeterHit h : hits )
-        {
-		//	Subdetector d = hit.getSubdetector();
-		//	double _sampling_fraction = d.getSamplingFraction();
-			double _sampling_fraction = 1.;
-			_decoder.setID(h.getCellID());
-            // this is a change...
-            // incorporate sampling fractions to get correct cluster energy
-            double e = h.getEnergy()/_samplingFraction;
-            if (e>_highestCellEnergy)
-            {
-                _highestCellEnergy = e;
-                _hottestCell = h;
-                // for now let highest energy cells determine location
-//                _isEndCap = cell.isEndcap();
-//                _isNorth = cell.isNorth();
-            }
-            // calculate the energy-weighted cluster width (second moment)
-            double dtheta=_vec.theta() - _decoder.getTheta();
-            double dphi=_vec.phi() - _decoder.getPhi();
-            // phi-wrap at 0:2pi?
-            if (dphi>Math.PI)
-            {
-                dphi-=2.*Math.PI;
-            }
-            if (dphi<-Math.PI)
-            {
-                dphi+=2.*Math.PI;
-            }
-            double dRw=(dtheta*dtheta + dphi*dphi)*e;
-            _width+=dRw;
-            // increment the energy deposited in this layer
-            _layerEnergy[_decoder.getLayer()]+=e;
-            _clusterEnergy+=e;
-            // increment the width (second moment of energy) in this layer
-            _layerWidth[_decoder.getLayer()]+=dRw;
-            //store the hit (x,y,z) coordinates
-            points[0][npoints] = _decoder.getX();
-            points[1][npoints] = _decoder.getY();
-            points[2][npoints] = _decoder.getZ();
-            npoints++;
-        }
-        // normalize the second moments
-        _width /= _clusterEnergy;
-        for(int i=0; i<layers; ++i)
-        {
-            _layerWidth[i]/=_clusterEnergy;
-        }
-        
-        // fit a straight line through the cells and store the results
-        PrincipalAxesLineFitter lf = new PrincipalAxesLineFitter();
-        lf.fit(points);
-        _centroid = lf.centroid();
-        _directionCosines = lf.dircos();
-		double dr = Math.sqrt( (_centroid[0]+_directionCosines[0])*(_centroid[0]+_directionCosines[0]) +
-					(_centroid[1]+_directionCosines[1])*(_centroid[1]+_directionCosines[1]) +
-					(_centroid[2]+_directionCosines[2])*(_centroid[2]+_directionCosines[2]) ) -
-					Math.sqrt(	(_centroid[0])*(_centroid[0]) +
-					(_centroid[1])*(_centroid[1]) +
-					(_centroid[2])*(_centroid[2]) ) ;
-		double sign = 1.;
-		if(dr < 0.)sign = -1.;
-		_itheta = Math.acos(_directionCosines[2]);
-		_iphi = Math.atan2(_directionCosines[1],_directionCosines[0]);
-
-        // finish up the cluster (base class method)
-//        calculateDerivedQuantities();
-    }
-    
-    /**
-     * Calculate the cluster four-momentum.
-     * The Lorentz four-vector is derived from the cluster cells.
-     *
-     */
-    public Lorentz4Vector calculateVec(List<CalorimeterHit> hits)
-    {
-        Lorentz4Vector sum = new Momentum4Vector();
-		double[] sums = {0.,0.,0.};
-		double wtsum = 0.;
-		for(int i=0;i<hits.size();i++)
-		{
-			CalorimeterHit hit = hits.get(i);
-		//	Subdetector d = hit.getSubdetector();
-		//	double sampling_fraction = d.getSamplingFraction();
-			double sampling_fraction = 1.;
-			double[] pos = new double[3];
-			_decoder.setID(hit.getCellID());
-			pos[0] = _decoder.getX();
-			pos[1] = _decoder.getY();
-			pos[2] = _decoder.getZ();
-			double wt = hit.getEnergy()/sampling_fraction;
-			wtsum += wt;
-			for(int j=0;j<3;j++)
-			{
-				sums[j] += wt*pos[j];
-			}
-		}
-		sum.plusEquals(new Momentum4Vector(sums[0], sums[1], sums[2], wtsum));
-        return sum;
-    }
-    
-    /**
-     * The cluster width (energy second moment).
-     *
-     * @return The cluster width
-     */
-    public double width()
-    {
-        return _width;
-    }
-    
-    /**
-     * The cluster four-momentum
-     *
-     * @return The Lorentz four-vector
-     */
-    public Lorentz4Vector vector()
-    {
-        return _vec;
-    }
-    
-    /**
-     * The constituent cells
-     *
-     * @return Vector of the CalorimeterHits constituting the cluster.
-     */
-    /**
-     * The cluster energy deposited in a specific layer
-     *
-     * @return  The cluster energy in layer <b>layer</b>
-     */
-    public double layerEnergy(int layer)
-    {
-        return _layerEnergy[layer];
-    }
-    
-    /**
-     * The cluster layer energies
-     *
-     * @return  The array of cluster energies in each layer.
-     */
-    public double[] layerEnergies()
-    {
-        return _layerEnergy;
-    }
-    
-    
-    /**
-     * The cluster energy corrected for sampling fractions
-     *
-     * @return  The cluster energy
-     */
-    public double clusterEnergy()
-    {
-        return _clusterEnergy;
-    }
-    
-    /**
-     * The energy of the highest energy cell in this cluster
-     *
-     * @return The energy of the highest energy cell in this cluster corrected by the sampling fraction.
-     */
-    public double highestCellEnergy()
-    {
-        return _highestCellEnergy;
-    }
-    
-    /**
-     * The CalorimeterHit in this cluster with the highest energy
-     *
-     * @return  The CalorimeterHit in this cluster with the highest energy
-     */
-    public CalorimeterHit hottestCell()
-    {
-        return _hottestCell;
-    }
-    
-    /**
-     * The cluster width (energy second moment) deposited in a specific layer
-     *
-     * @return  The cluster width in layer <b>layer</b>
-     */
-    public double layerWidth(int layer)
-    {
-        return _layerWidth[layer];
-    }
-    
-    /**
-     * The unweighted spatial centroid (x,y,z) of the cluster line fit
-     *
-     * @return The unweighted spatial centroid (x,y,z) of the cluster
-     */
-    public double[] centroid()
-    {
-        return _centroid;
-    }
-    
-    /**
-     * The direction cosines of the cluster line fit
-     *
-     * @return The direction cosines of the cluster
-     */
-    public double[] directionCosines()
-    {
-        return _directionCosines;
-    }
-    
-    
-    /**
-     * Returns topological position of cluster.
-     *
-     * @return true if in EndCap
-     */
-    public boolean isEndCap()
-    {
-        return _isEndCap;
-    }
-    
-    
-    /**
-     * Returns topological position of cluster.
-     *
-     * @return  true if in "North" EndCap
-     */
-    public boolean isNorth()
-    {
-        return _isNorth;
-    }
-    
-    public void setChisq(double chisq)
-    {
-        _chisq = chisq;
-    }
-    
-    public double chisq()
-    {
-        return _chisq;
-    }
-	public double[] getPosition()
-	{
-		return _centroid;
-	}
-	public double[] getPositionError()
-	{
-		double[] positionError = {0.,0.,0.,0.,0.,0.};
-		return positionError;
-	}
-	public double getIPhi()
-	{
-		return _iphi;
-	}
-	public double getITheta()
-	{
-		return _itheta;
-	}
-	public double[] getDirectionError()
-	{
-		double[] directionError = {0.,0.,0.,0.,0.,0.};
-		return directionError;
-	}
-	public double[] getShapeParameters()
-	{
-		double[] shapeParameters = {0.,0.,0.,0.,0.,0.};
-		shapeParameters[0] = _width;
-		return shapeParameters;
-	}
-    
-    
-}
-
CVSspam 0.2.8