lcsim/src/org/lcsim/recon/cluster/util
diff -N SmallClusterFindMother.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ SmallClusterFindMother.java 1 Apr 2008 01:21:14 -0000 1.1
@@ -0,0 +1,281 @@
+/*
+ * SmallClusterFindMother.java
+ *
+ * Created on February 17, 2008, 10:52 AM
+ *
+ * To attache the smaller cluster around a bigger one to the the bigger one
+ */
+
+package org.lcsim.recon.cluster.util;
+import java.util.List;
+import java.util.ArrayList;
+import org.lcsim.event.Cluster;
+import org.lcsim.recon.cluster.util.BasicCluster;
+import org.lcsim.recon.cluster.util.ClusterESort;
+import java.util.Collections;
+import org.lcsim.recon.cluster.util.ClusterIDCheater;
+import org.lcsim.event.MCParticle;
+import org.lcsim.event.CalorimeterHit;
+/**
+ *
+ * @author Qingmin Zhang
+ */
+public class SmallClusterFindMother {
+ double minDistanceDiff = 200.0;
+ double minAngle = .2;
+ double minERatio = .1;
+ int totalAttach = 0;
+ int effAttach = 0;
+ List<MCParticle> fsParticles = new ArrayList<MCParticle>();
+ /** Creates a new instance of SmallClusterFindMother */
+ public SmallClusterFindMother()
+ {
+ }
+ public SmallClusterFindMother(List<MCParticle> fs)
+ {
+ fsParticles = fs;
+ }
+ public SmallClusterFindMother(double dis,double angle,double eRatio)
+ {
+ minDistanceDiff = dis;
+ minAngle = angle;
+ minERatio = eRatio;
+ }
+ public SmallClusterFindMother(double dis) //for muon Detector especially near the boundary between endcap and barrel
+ {
+ minDistanceDiff = dis;
+ }
+ public List<Cluster> attachToMother(List<Cluster> originClusters)
+ {
+
+ List<Cluster> startClusters = new ArrayList<Cluster>();
+ startClusters.addAll(originClusters);
+ List<Cluster> finalClusters = new ArrayList<Cluster>();
+ boolean continueFlag = true;
+ while(continueFlag){
+ finalClusters.clear();
+ //order by the energy of Cluster
+ Collections.sort(startClusters, new ClusterESort());
+ int size = startClusters.size();
+ boolean[] used = new boolean[size];
+ List<Integer> child = new ArrayList<Integer>();
+ List<Integer> mother = new ArrayList<Integer>();
+ for(int i =0 ;i<size;i++)
+ used[i] = false;
+
+ for(int i=size-1;i>=0;i--)
+ {
+ if(!used[i]){
+ double complexIndex = 9999.0; // = angle*(E1/E)*d
+ int motherID = -1;
+ for(int j = 0;j<i;j++)
+ {
+ double a = angle(startClusters.get(i),startClusters.get(j));
+ double eRatio = startClusters.get(i).getEnergy()/startClusters.get(j).getEnergy();
+ double dis = distance(startClusters.get(i),startClusters.get(j));
+ if(a<=minAngle&&eRatio<=minERatio&&dis<=minDistanceDiff)
+ {
+ if(complexIndex >a*eRatio*dis)
+ { complexIndex = a*eRatio*dis;
+ motherID = j;
+ }
+ }
+ }
+ if(motherID!=-1)
+ {
+ child.add(i);
+ mother.add(motherID);
+ used[i] = true;
+ used[motherID] = true;
+ }
+ }
+ }
+ //process clusters without dependent and clusters not be depended
+ for(int i = 0;i<size;i++)
+ if(!used[i])
+ finalClusters.add(startClusters.get(i));
+ boolean[] pairUsed = new boolean[child.size()];
+ for(int i=0;i<child.size();i++)
+ pairUsed[i] = false;
+ //process related clusters: attach the smaller one to the bigger one
+ for(int i=0;i<child.size();i++)
+ {
+ if(!pairUsed[i]){
+ BasicCluster unite = (BasicCluster)startClusters.get(mother.get(i));
+ for(int j=0;j<mother.size();j++)
+ if(!pairUsed[j]&&mother.get(j)==mother.get(i))
+ {
+ Cluster childCluster = startClusters.get(child.get(i));
+ totalAttach++;
+ if(fromSameParticle(fsParticles,unite,childCluster))
+ effAttach++;
+ unite.addCluster(childCluster);
+ pairUsed[j]= true;
+
+ }
+ finalClusters.add(unite);
+ }
+ }
+ if(startClusters.size()==finalClusters.size())
+ continueFlag = false;
+ //prepare for the next possible loop
+ startClusters.clear();
+ for(Cluster c: finalClusters)
+ startClusters.add(c);
+ }
+ return finalClusters;
+ }
+
+ public double angle(Cluster c, Cluster c1)
+ {
+ double[] pos = c.getPosition();
+ double[] pos1 = c1.getPosition();
+ double[] vec = new double[3];
+ for(int i = 0;i<3;i++)
+ vec[i] = pos1[i];//pos1[i]-pos[i];
+ double dist1 = Math.sqrt(pos[0]*pos[0]+pos[1]*pos[1]+pos[2]*pos[2]);
+ double dist2 = Math.sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
+ double dot = pos[0]*vec[0]+pos[1]*vec[1]+pos[2]*vec[2];
+ double angle = Math.acos(dot/(dist1*dist2));
+ return angle;
+ }
+ public List<Cluster> attachToMotherForMuon(List<Cluster> originClusters,int minSize)
+ {
+
+ List<Cluster> startClusters = new ArrayList<Cluster>();
+ startClusters.addAll(originClusters);
+ List<Cluster> finalClusters = new ArrayList<Cluster>();
+ boolean continueFlag = true;
+ while(continueFlag){
+ finalClusters.clear();
+ //order by the energy of Cluster
+ Collections.sort(startClusters, new ClusterESort());
+ int size = startClusters.size();
+ boolean[] used = new boolean[size];
+ List<Integer> child = new ArrayList<Integer>();
+ List<Integer> mother = new ArrayList<Integer>();
+ for(int i =0 ;i<size;i++)
+ used[i] = false;
+
+ for(int i=size-1;i>=0;i--)
+ {
+ if(!used[i]){
+ double complexIndex = 9999.0;
+ int motherID = -1;
+ for(int j = 0;j<i;j++)
+ {
+ double dis = minDistance(startClusters.get(i),startClusters.get(j));
+ if(dis < minDistanceDiff)
+ {
+ if(complexIndex >dis)
+ { complexIndex = dis;
+ motherID = j;
+ }
+ }
+ }
+ if(motherID!=-1)
+ {
+ child.add(i);
+ mother.add(motherID);
+ used[i] = true;
+ used[motherID] = true;
+ }
+ }
+ }
+ //process clusters without dependent and clusters not be depended
+ for(int i = 0;i<size;i++)
+ if(!used[i])
+ finalClusters.add(startClusters.get(i));
+ boolean[] pairUsed = new boolean[child.size()];
+ for(int i=0;i<child.size();i++)
+ pairUsed[i] = false;
+ //process related clusters: attach the smaller one to the bigger one
+ for(int i=0;i<child.size();i++)
+ {
+ if(!pairUsed[i]){
+ BasicCluster unite = (BasicCluster)startClusters.get(mother.get(i));
+ for(int j=0;j<mother.size();j++)
+ if(!pairUsed[j]&&mother.get(j)==mother.get(i))
+ {
+ Cluster childCluster = startClusters.get(child.get(i));
+ unite.addCluster(childCluster);
+ pairUsed[j]= true;
+
+ }
+ finalClusters.add(unite);
+ }
+ }
+ if(startClusters.size()==finalClusters.size())
+ continueFlag = false;
+ //prepare for the next possible loop
+ startClusters.clear();
+ for(Cluster c: finalClusters)
+ startClusters.add(c);
+ }
+ List<Cluster> fClusters = new ArrayList<Cluster>();
+ for(Cluster c: finalClusters)
+ { if(c.getSize()>= minSize)
+ fClusters.add(c);
+ }
+ return fClusters;
+ }
+ public double distance(Cluster c, Cluster c1)
+ {
+ double[] pos = c.getPosition();
+ double[] pos1 = c1.getPosition();
+ double[] dis = new double[3];
+ for(int i =0;i<3;i++)
+ dis[i]= pos[i]-pos1[i];
+ double dist = Math.sqrt(dis[0]*dis[0]+dis[1]*dis[1]+dis[2]*dis[2]);
+ return dist;
+ }
+ public double minDistance(Cluster c, Cluster c1)
+ {
+ double mindist = 9999.;
+ for(CalorimeterHit p:c1.getCalorimeterHits())
+ {
+ double[] pos = p.getPosition();
+ for(CalorimeterHit h:c.getCalorimeterHits())
+ {
+ double[] hp = h.getPosition();
+ double d = Math.sqrt((hp[0]-pos[0])*(hp[0]-pos[0]) +(hp[1]-pos[1])*(hp[1]-pos[1]) +(hp[2]-pos[2])*(hp[2]-pos[2]));
+ if(d < mindist)mindist = d;
+ }
+ }
+ return mindist;
+ }
+ public double minAngle(Cluster c, Cluster c1)
+ {
+ double minA = 99.;
+ for(CalorimeterHit p:c1.getCalorimeterHits())
+ {
+ double[] pos = p.getPosition();
+ for(CalorimeterHit h:c.getCalorimeterHits())
+ {
+ double[] hp = h.getPosition();
+ double dist1 = Math.sqrt(pos[0]*pos[0]+pos[1]*pos[1]+pos[2]*pos[2]);
+ double dist2 = Math.sqrt(hp[0]*hp[0]+hp[1]*hp[1]+hp[2]*hp[2]);
+ double dot = pos[0]*hp[0]+pos[1]*hp[1]+pos[2]*hp[2];
+ double angle = Math.acos(dot/(dist1*dist2));
+ if(angle < minA) minA = angle;
+ }
+ }
+ return minA;
+ }
+public boolean fromSameParticle(List<MCParticle> fs,Cluster c1, Cluster c2)
+ {
+ ClusterIDCheater idCheater = new ClusterIDCheater();
+ if(idCheater.getMCID(fs,c1)==idCheater.getMCID(fs,c2))
+ return true;
+ else
+ return false;
+ }
+public int getTotalAttach()
+{
+ return totalAttach;
+}
+public int getEffAttach()
+{
+ return effAttach;
+}
+}
\ No newline at end of file