8 added files
lcsim/src/org/lcsim/recon/cluster/mipfinder
diff -N AbstractHitType.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ AbstractHitType.java 2 Jan 2006 21:45:19 -0000 1.1
@@ -0,0 +1,34 @@
+package org.lcsim.recon.cluster.mipfinder;
+
+import java.lang.String;
+import org.lcsim.event.CalorimeterHit;
+
+/**
+ Abstract Hit. Designed for use with
+ LCDG4 Geant files
+
+
+ @author Wolfgang F. Mader ([log in to unmask])
+ @version $Id: AbstractHitType.java,v 1.1 2006/01/02 21:45:19 mcharles Exp $
+
+ Modification Log:
+ -- 07/22/2004 Version 1.0
+ -- 09/26/2005 Ported to org.lcsim by Mat
+*/
+public abstract class AbstractHitType {
+
+ public abstract boolean isValid(CalorimeterHit h,
+ HitCollection hc);
+ public Object getIdentifier(){ return ((Object) identifier); }
+ public boolean useInSeeds(){
+ return lUseInSeeds;
+ }
+ public void useInSeeds(boolean b) {
+ if ( lWelcome ) System.out.println(identifier+" used in MIPSeeds: "+b);
+ lUseInSeeds = b;
+ }
+ protected boolean lUseInSeeds = true;
+
+ protected String identifier;
+ protected static boolean lWelcome = true;
+}
lcsim/src/org/lcsim/recon/cluster/mipfinder
diff -N DoubleHit.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ DoubleHit.java 2 Jan 2006 21:45:19 -0000 1.1
@@ -0,0 +1,83 @@
+package org.lcsim.recon.cluster.mipfinder;
+
+import org.lcsim.event.CalorimeterHit;
+import java.util.Vector;
+import org.lcsim.geometry.IDDecoder;
+import org.lcsim.geometry.CalorimeterIDDecoder;
+
+/**
+ Double Hit. Designed for use with
+ LCDG4 Geant files
+
+
+ @author Wolfgang F. Mader ([log in to unmask])
+ @version $Id: DoubleHit.java,v 1.1 2006/01/02 21:45:19 mcharles Exp $
+
+ Modification Log:
+ -- 07/22/2004 Version 1.0
+ -- 09/26/2005 Converted to org.lcsim by Mat
+*/
+
+public class DoubleHit extends AbstractHitType{
+
+ public DoubleHit(){
+ identifier = "doubleHit";
+ if ( lWelcome ){
+ System.out.println(identifier+" used in MIP reconstruction");
+ lWelcome = false;
+ }
+ }
+
+ /**
+ * Check whether the hit matches the DoubleHit criteria. A DoubleHit is
+ * allowed two MIP hits in the same layer but only one MIP hit in the
+ * layers above and below. The implementation is a little complicated
+ * because some (but not all) of the MIP hits have been removed from
+ * the hit collection, so what we do is require that there is exactly
+ * one unremoved hit in the same layer and exactly one unremoved hit
+ * in the adjacent layers (i.e. one hit total in adjacent layers,
+ * not one per adjacent layer).
+ */
+ public boolean isValid(CalorimeterHit h,
+ HitCollection hc )
+ {
+ // Find all neighbouring cells:
+ int dLayer = 1;
+ int dU = 1;
+ int dV = 1;
+ CalorimeterIDDecoder id = (CalorimeterIDDecoder) h.getIDDecoder();
+ id.setID(h.getCellID());
+ long[] neighbours = id.getNeighbourIDs(dLayer, dU, dV);
+
+ // What layer is the main hit in?
+ id.setID(h.getCellID());
+ int mainLayer = id.getLayer();
+
+ // For each nearby hit, whether it is in the same layer as
+ // the main hit or one layer away.
+ int nNeighbourHitsInSameLayer = 0;
+ int nNeighbourHitsInOtherLayer = 0;
+ for ( int i=0; i<neighbours.length; i++ ){
+ CalorimeterHit hit = hc.find(neighbours[i]);
+ if ( hit != null ){
+ // Check the layer indices:
+ id.setID(hit.getCellID());
+ int layer = id.getLayer();
+ if (layer == mainLayer) {
+ nNeighbourHitsInSameLayer++;
+ } else if ( (layer==mainLayer-1) || (layer==mainLayer+1) ) {
+ nNeighbourHitsInOtherLayer++;
+ } else {
+ throw new AssertionError("Invalid layer "+layer+"; allowed layers: "+(mainLayer-1)+", "+mainLayer+", "+(mainLayer+1));
+ }
+ }
+ }
+
+ if (nNeighbourHitsInSameLayer==1 && nNeighbourHitsInOtherLayer==1) {
+ // Meets criteria (see comment at top of method)
+ return true;
+ } else {
+ return false;
+ }
+ }
+}
lcsim/src/org/lcsim/recon/cluster/mipfinder
diff -N Flash.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ Flash.java 2 Jan 2006 21:45:19 -0000 1.1
@@ -0,0 +1,186 @@
+package org.lcsim.recon.cluster.mipfinder;
+
+import java.util.Hashtable;
+import java.util.Vector;
+import java.util.Enumeration;
+import java.util.Collection;
+
+import org.lcsim.event.CalorimeterHit;
+
+/**
+ Implementation of Hit Collection Flash. Designed for use with
+ LCDG4 Geant files
+
+
+ @author Wolfgang F. Mader ([log in to unmask])
+ @version $Id: Flash.java,v 1.1 2006/01/02 21:45:19 mcharles Exp $
+
+ Modification Log:
+ -- 07/22/2004 Version 1.0
+ -- 09/26/2005 Converted to org.lcsim by Mat
+*/
+
+// Hits are stored in:
+//
+// * Hashtable<Long, CalorimeterHit> flashVector
+// * Object[] array
+//
+// The array is indexed by hashcode of the hit CellID.
+// Each entry in the array is initially null. If filled
+// once, it is set to the hit. If filled again, it is
+// changed into a vector that holds all hits with which
+// it has been filled.
+
+public class Flash extends HitCollection {
+ public Flash(int size) {
+ flashVector = new Hashtable<Long, CalorimeterHit>();
+ array = new Object[137*size/50];
+ }
+
+ /**
+ * Internal routine to store a CalorimeterHit in the array
+ */
+ void put(CalorimeterHit h) {
+ flashVector.put(new Long(h.getCellID()), h);
+
+ int i = hash(h.getCellID());
+ if (array[i] == null) {
+ // Not yet filled => set to hit
+ array[i] = h;
+ } else if (array[i] instanceof CalorimeterHit) {
+ // Already filled exactly once.
+ // Switch from hit to vector storage and fill:
+ Vector<CalorimeterHit> v = new Vector<CalorimeterHit>();
+ CalorimeterHit existingHit = (CalorimeterHit) (array[i]);
+ v.addElement(existingHit);
+ v.addElement(h);
+ array[i] = v;
+ } else {
+ // If not null or CalorimeterHit, should be a Vector.
+ // Already filled multiple times => fill again
+ Vector<CalorimeterHit> v = (Vector<CalorimeterHit>) array[i];
+ v.add(h);
+ }
+ return;
+ }
+
+ /**
+ * Internal routine to search for a CalorimeterHit (by CellID) in the Flash
+ */
+ CalorimeterHit find(CalorimeterHit thisHit) {
+ long id = thisHit.getCellID();
+ CalorimeterHit h = find(id);
+ return h;
+ }
+
+ /**
+ * Internal routine to look up a CalorimeterHit given its CellID
+ */
+ CalorimeterHit find(long id) {
+ // Convert CellID into a hash code (for use as array index):
+ int i = hash(id);
+ // Now, what's at that point in the array?
+ if (array[i] == null) {
+ // Nothing
+ return null;
+ } else if (array[i] instanceof CalorimeterHit) {
+ // A single CalorimeterHit. Need to verify that full CellID
+ // matches as well as hashcode
+ CalorimeterHit h = (CalorimeterHit) array[i];
+ if (h.getCellID() == id) {
+ return h;
+ } else {
+ return null;
+ }
+ } else {
+ // If not null or CalorimeterHit, should be a Vector.
+ // Check for a fully matched hit. If there is more than
+ // one, just return the first.
+ Vector<CalorimeterHit> v = (Vector<CalorimeterHit>) array[i];
+ for (CalorimeterHit hit : v) {
+ if (hit.getCellID() == id) {
+ return hit;
+ }
+ }
+ // No matching hit
+ return null;
+ }
+ }
+
+ /**
+ * Internal routine to remove a CalorimeterHit from the array.
+ */
+ void remove(CalorimeterHit h) {
+ // Remove from the Hashtable:
+ long targetCellID = h.getCellID();
+ flashVector.remove(new Long(targetCellID));
+
+ // Remove from the array. Start by computing the index (hashcode):
+ int i = hash(h.getCellID());
+ if (array[i] == null) {
+ // Nothing to remove
+ } else if (array[i] instanceof CalorimeterHit) {
+ // There's a hit -- check if it matches
+ CalorimeterHit hitInArray = (CalorimeterHit) (array[i]);
+ if (hitInArray.getCellID() == targetCellID) {
+ // Match => remove
+ array[i] = null;
+ }
+ } else {
+ // If not null or CalorimeterHit, should be a Vector.
+ // Several hits with that hash. Check them all:
+ Vector<CalorimeterHit> v = (Vector<CalorimeterHit>) array[i];
+ Vector<CalorimeterHit> vHitsToRemove = new Vector<CalorimeterHit>();
+ for (CalorimeterHit currentHit : v) {
+ if (currentHit.getCellID() == targetCellID) {
+ vHitsToRemove.add(currentHit);
+ }
+ }
+ // Remove any matching hits
+ for (CalorimeterHit currentHit : vHitsToRemove) {
+ boolean removedOK = v.remove(currentHit);
+ if (!removedOK) { throw new AssertionError("Hit "+h+" not removed from HitCollection"); }
+ }
+ }
+ }
+
+ /**
+ * Internal routine to check the number of hits in the Flash
+ */
+ int getNumberOfHits(){
+ return flashVector.size();
+ }
+
+ /**
+ * Internal routine to get all hits in the Flash
+ */
+ Enumeration<CalorimeterHit> getHits(){
+ return flashVector.elements();
+ }
+
+ /**
+ * Internal routine to get all hits in the Flash, in the form of a
+ * Vector. This is a copy, i.e. add/remove actions on the returned
+ * Vector will not affect the Flash.
+ */
+ Vector<CalorimeterHit> getVector(){
+ Vector<CalorimeterHit> v = new Vector<CalorimeterHit>();
+ Collection<CalorimeterHit> hits = flashVector.values();
+ v.addAll(hits);
+ return v;
+ }
+
+ /**
+ * Internal routine to compute the hash of a CellID.
+ */
+ private int hash(long i){
+ long masked = (0x7fffffff & i);
+ long output = masked % array.length;
+ return (int) output;
+ }
+
+
+ private Object[] array;
+ private Hashtable<Long, CalorimeterHit> flashVector;
+ private int numberOfHits;
+}
lcsim/src/org/lcsim/recon/cluster/mipfinder
diff -N HitCollection.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ HitCollection.java 2 Jan 2006 21:45:19 -0000 1.1
@@ -0,0 +1,43 @@
+package org.lcsim.recon.cluster.mipfinder;
+
+import java.util.List;
+import java.util.Vector;
+import java.util.Enumeration;
+
+import org.lcsim.event.CalorimeterHit;
+
+/**
+ Driver for Track Reconstruction in Event. Designed for use with
+ LCDG4 Geant files
+
+
+ @author Wolfgang F. Mader ([log in to unmask])
+ @version $Id: HitCollection.java,v 1.1 2006/01/02 21:45:19 mcharles Exp $
+
+ Modification Log:
+ -- 07/22/2004 Version 1.0
+ -- 09/26/2005 Ported to org.lcsim by Mat
+*/
+
+public abstract class HitCollection {
+//
+// Constructor Summary
+//
+ public HitCollection(){
+ }
+//
+// Method Summary
+//
+ abstract void put(CalorimeterHit thisHit);
+ abstract CalorimeterHit find(CalorimeterHit thisHit);
+ abstract CalorimeterHit find(long id);
+ abstract void remove(CalorimeterHit thisHit);
+ abstract int getNumberOfHits();
+ abstract Enumeration getHits();
+ abstract Vector getVector();
+ public void fill(List<CalorimeterHit> hits){
+ for (CalorimeterHit hit : hits) {
+ this.put(hit);
+ }
+ }
+}
lcsim/src/org/lcsim/recon/cluster/mipfinder
diff -N MIPCluster.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ MIPCluster.java 2 Jan 2006 21:45:19 -0000 1.1
@@ -0,0 +1,93 @@
+package org.lcsim.recon.cluster.mipfinder;
+
+import org.lcsim.event.CalorimeterHit;
+import org.lcsim.event.Cluster;
+import org.lcsim.recon.cluster.util.BasicCluster;
+import org.lcsim.geometry.IDDecoder;
+
+
+/**
+ Class for Cluster Candidates
+
+ @version $Id: MIPCluster.java,v 1.1 2006/01/02 21:45:19 mcharles Exp $
+ @author [log in to unmask]
+*/
+
+public class MIPCluster extends BasicCluster {
+
+ public MIPCluster(int nSeeds, int dir){
+ super();
+ nSeedLayers = nSeeds;
+ direction = dir;
+ }
+
+ public double[] getShowerCoordinates(){
+ /**
+ returns the 3D Coordinates of the last MIP-Hit
+ */
+ if (hits.size() > 0) {
+ int lastIndex = hits.size() - 1;
+ CalorimeterHit lastHit = hits.get(lastIndex);
+ IDDecoder id = lastHit.getIDDecoder();
+ id.setID(lastHit.getCellID());
+ return id.getPosition();
+ } else {
+ // Not enough hits
+ return null;
+ }
+ }
+
+ public boolean isGoodMIP(){
+ boolean lIsGoodMIP = true;
+ lIsGoodMIP = lIsGoodMIP && hits.size() >= 3;
+ lIsGoodMIP = lIsGoodMIP && numberOfHitsInSeedLayers();
+ return lIsGoodMIP;
+ }
+
+ public boolean doesFork(){
+ /**
+ Returns <tt>true</tt> or <tt>false</tt> depending on
+ whether the MIP track forks or not
+ */
+ return lFork;
+ }
+ public void doesFork(boolean b){
+ /**
+ Sets the <tt>Fork</tt> Flag
+ */
+ lFork = b;
+ }
+
+ private boolean numberOfHitsInSeedLayers(){
+ int[] nHits = new int[nSeedLayers];
+
+ int j=0;
+ for (CalorimeterHit hit : hits) {
+ IDDecoder id = hit.getIDDecoder();
+ id.setID(hit.getCellID());
+ int layer = id.getLayer();
+
+ if ( j < nSeedLayers ) {
+ nHits[j]++;
+ }
+ j++;
+ }
+
+ int nHSum = 0;
+ boolean lNOH = true;
+ for ( int i=0; i<nSeedLayers; i++ ){
+ lNOH = lNOH && nHits[i] <= 1;
+ nHSum += nHits[i];
+ }
+
+ lNOH = lNOH && nHSum <= nSeedLayers && nHSum >= nSeedLayers-1;
+ return lNOH;
+ }
+
+ private int firstLayer = 0;
+ private int nSeedLayers = 4;
+ private int direction = +1;
+
+ private boolean lFork = false;
+}
+
lcsim/src/org/lcsim/recon/cluster/mipfinder
diff -N MIPClusterBuilder.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ MIPClusterBuilder.java 2 Jan 2006 21:45:19 -0000 1.1
@@ -0,0 +1,304 @@
+package org.lcsim.recon.cluster.mipfinder;
+
+import java.util.List;
+import java.util.Hashtable;
+import java.util.Vector;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Set;
+
+import org.lcsim.event.CalorimeterHit;
+import org.lcsim.geometry.IDDecoder;
+import org.lcsim.event.Cluster;
+import org.lcsim.geometry.CalorimeterIDDecoder;
+
+
+/**
+ MIPClusterBuilder
+ -- Recursive Clustering Algorimthm
+
+ Package: MIP
+
+ Version 1.0
+
+ Modification Log:
+ -- 23 March 2005: First Version
+ -- 23 Sept 2005: Converted to org.lcsim by Mat
+
+ (c) [log in to unmask]
+*/
+
+public class MIPClusterBuilder{
+
+ public MIPClusterBuilder( List<CalorimeterHit> hits,
+ List<AbstractHitType> hitTypeList)
+ {
+ thisHits = hits;
+ hitTypes = hitTypeList;
+ }
+
+ public void initialize(){
+//
+// Initialize Flash
+//
+ flash = new Flash(thisHits.size());
+ for (CalorimeterHit hit : thisHits) {
+ flash.put(hit);
+ // Find layer:
+ IDDecoder id = hit.getIDDecoder();
+ id.setID(hit.getCellID());
+ Integer layer = new Integer(id.getLayer());
+ // Store the hit in the right per-layer list:
+ if ( hitTable.containsKey(layer) ) {
+ Vector<CalorimeterHit> v = hitTable.get(layer);
+ v.add(hit);
+ } else {
+ Vector<CalorimeterHit> v = new Vector<CalorimeterHit>();
+ v.add(hit);
+ hitTable.put(layer, v);
+ }
+ }
+
+
+ if ( !lUserNucleii ){
+ int j = firstLayer;
+ for ( int i=0; i<nSeedLayers; i++ ){
+ if ( hitTable.containsKey(new Integer(j)) ) {
+ Vector<CalorimeterHit> v = hitTable.get(new Integer(j));
+//
+// Require minimum energy for nucleii hits
+//
+ for (CalorimeterHit hit : v) {
+ if ( hit.getRawEnergy() > eMin && hit.getRawEnergy() < eMax ) {
+ nucleii.add(hit);
+ }
+ }
+ }
+ j += direction;
+ }
+ }
+//
+// Debug output
+//
+ if ( lDebug ){
+ Set<Integer> layers = hitTable.keySet();
+ for (Integer i : layers) {
+ Vector<CalorimeterHit> v = hitTable.get(i);
+ System.out.println(this.getClass().getName()+" init: layer "+i+": "+v.size()+" hits");
+ for (CalorimeterHit hit : v) {
+ IDDecoder id = hit.getIDDecoder();
+ id.setID(hit.getCellID());
+ System.out.println(this.getClass().getName()+" init: E="+hit.getRawEnergy()+", hit="+hit+", theta="+id.getTheta()+", phi="+id.getPhi());
+ }
+ }
+ }
+ }
+
+//
+// do the Clustering
+//
+ public List<Cluster> getMIPClusterList(){
+ List<Cluster> vCluster = new Vector<Cluster>();
+
+ for (CalorimeterHit hit : nucleii) {
+
+ if ( flash.find(hit) == null ) {
+ // Someone fed us a nucleus that's not in the hit list
+ // It can also be that the hit was used in a previous cluster.
+ continue;
+ }
+
+ MIPCluster cluster = new MIPCluster(nSeedLayers, direction);
+ iSingleHitsInLayer = new HashMap<Integer,Integer> ();
+
+ if ( validate(hit) ){
+ cluster.addHit(hit);
+ flash.remove(hit);
+
+ extend(cluster,hit,flash);
+ if ( cluster.isGoodMIP() ) {
+//
+// See if MIP forks. Criterion is two SingeHits in the same Layer
+//
+ boolean lFork = false;
+ Set<Integer> layers = iSingleHitsInLayer.keySet();
+ for (Integer currentTestLayer : layers) {
+ Integer hitsInLayer = iSingleHitsInLayer.get(currentTestLayer);
+ if (hitsInLayer.intValue() >= 2) {
+ lFork = true;
+ }
+ }
+
+ cluster.doesFork(lFork);
+ vCluster.add(cluster);
+ }
+ }
+ }
+//
+// Debug output
+//
+ if ( lDebug ){
+ for (Cluster cluster : vCluster) {
+ System.out.println(this.getClass().getName()+" found cluster: "+cluster);
+
+ int i=0;
+ for (CalorimeterHit hit : cluster.getCalorimeterHits()) {
+ IDDecoder id = hit.getIDDecoder();
+ id.setID(hit.getCellID());
+ System.out.println(this.getClass().getName()+" found cluster: hit #"+i+":"+hit+", layer="+id.getLayer()+", theta="+id.getTheta()+", phi="+id.getPhi());
+ i++;
+ }
+ }
+ }
+
+ return vCluster;
+ }
+
+ private void extend(MIPCluster c,
+ CalorimeterHit h,
+ HitCollection hc )
+ {
+ int dLayer = 1;
+ int dU = 1;
+ int dV = 1;
+ CalorimeterIDDecoder id = (CalorimeterIDDecoder) h.getIDDecoder();
+ id.setID(h.getCellID());
+ long[] neighbours = id.getNeighbourIDs(dLayer, dU, dV);
+
+ Vector<CalorimeterHit> vHits = new Vector<CalorimeterHit>();
+
+ int iNeighboursInNextLayer = 0;
+ for ( int i=0; i<neighbours.length; i++ ){
+ CalorimeterHit hit = hc.find(neighbours[i]);
+
+ if ( hit != null ) {
+ id.setID(h.getCellID());
+ int iLayer = id.getLayer() * direction;
+ id.setID(hit.getCellID());
+ int jLayer = id.getLayer() * direction;
+
+ if ( jLayer == iLayer+1 ) {
+
+ iNeighboursInNextLayer++;
+ if ( validate(hit) ) {
+
+ c.addHit(hit);
+ hc.remove(hit);
+ extend(c,hit,hc);
+ }
+ }
+ }
+ }
+
+ }
+
+ private boolean validate(CalorimeterHit h){
+ boolean lValidate = false;
+
+ for (AbstractHitType aType : hitTypes) {
+ if ( isInSeedLayer(h) && !aType.useInSeeds() ) {
+ continue;
+ }
+ if ( aType.isValid(h, flash) ){
+ lValidate = true;
+ }
+
+ if ( lValidate && (aType instanceof SingleHit) ){
+ IDDecoder id = h.getIDDecoder();
+ id.setID(h.getCellID());
+ Integer layer = new Integer(id.getLayer());
+ Integer countHitsInLayer = iSingleHitsInLayer.get(layer);
+ if (countHitsInLayer != null) {
+ // Increment
+ countHitsInLayer = new Integer(countHitsInLayer.intValue()+1);
+ } else {
+ // Haven't found a hit in that layer yet, so this is the first
+ countHitsInLayer = new Integer(1);
+ }
+ iSingleHitsInLayer.put(layer, countHitsInLayer);
+ }
+ }
+ return lValidate;
+ }
+
+ private boolean isInSeedLayer(CalorimeterHit hit){
+ IDDecoder id = hit.getIDDecoder();
+ id.setID(hit.getCellID());
+ int layer = id.getLayer();
+ return ( direction*layer >= direction*firstLayer &&
+ direction*layer < direction*(firstLayer+direction*nSeedLayers) );
+ }
+
+ private List<CalorimeterHit> thisHits;
+ private Hashtable<Integer, Vector<CalorimeterHit> > hitTable = new Hashtable<Integer, Vector<CalorimeterHit> > ();
+ private List<AbstractHitType> hitTypes;
+
+ private Flash flash;
+ private List<CalorimeterHit> nucleii = new Vector<CalorimeterHit>();
+ private boolean lUserNucleii = false;
+
+ public void provideNucleii(List<CalorimeterHit> v){
+ nucleii = v;
+ lUserNucleii = true;
+ }
+
+ private double eMin = 0.;
+ private double eMax = 1000.;
+
+ public void setMinimumHitEnergy(double v){
+ eMin = v;
+ }
+ public double getMinimumHitEnergy(){
+ return eMin;
+ }
+ public void setMaximumHitEnergy(double v){
+ eMax = v;
+ }
+ public double getMaximumHitEnergy(){
+ return eMax;
+ }
+
+ public void setNumberOfSeedLayers(int i){
+ nSeedLayers = i;
+ }
+
+ public int getNumberOfSeedLayers(int i){
+ return ((int) nSeedLayers);
+ }
+
+ public void setFirstLayer(int i){
+ firstLayer = i;
+ }
+ public int getFirstLayer(int i){
+ return ((int) firstLayer);
+ }
+
+ public void setDirectionAndFirstLayer(int newDir, int newFL){
+ setDirection(newDir);
+ setFirstLayer(newFL);
+ }
+
+ public void setDirection(int i){
+ if ( Math.abs(i) != 1 )
+ throw new AssertionError("Direction has to be +/-1");
+ direction = i;
+ }
+
+ public int getDirection(int i){
+ return ((int) direction );
+ }
+
+ private int nSeedLayers = 4;
+ private int firstLayer = 0;
+ private int direction = 1;
+ private Map<Integer, Integer> iSingleHitsInLayer;
+
+ private Vector<Cluster> vMIP = new Vector<Cluster>();
+ private int depth = 0;
+
+ private boolean lDebug = false;
+
+ public void setDebugMode(boolean b){
+ lDebug = b;
+ }
+}
lcsim/src/org/lcsim/recon/cluster/mipfinder
diff -N MIPClusterDriver.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ MIPClusterDriver.java 2 Jan 2006 21:45:19 -0000 1.1
@@ -0,0 +1,245 @@
+package org.lcsim.recon.cluster.mipfinder;
+
+import java.util.List;
+import java.util.Vector;
+import java.io.IOException;
+
+import org.lcsim.util.Driver;
+import org.lcsim.event.EventHeader;
+import org.lcsim.event.Cluster;
+import org.lcsim.event.CalorimeterHit;
+
+
+/**
+ Main Processor for MIP Clustering.
+ <p>
+ Example of Use:
+ <p><blockquote><pre>
+ MIPClusterDriver MIPprocessor = new MIPClusterDriver("EMCal");
+ MIPprocessor.setClusterName("MIPCluster EMCal");
+ //
+ // Now define the HIT Types
+ //
+ List<AbstractHitType> hitTypes = new Vector<AbstractHitType>();
+
+ SingleHit sH = new SingleHit();
+ DoubleHit dH = new DoubleHit();
+ //
+ // Say which HIT types to use for MIP seeds
+ //
+ sH.useInSeeds(true);
+ dH.useInSeeds(false);
+
+ hitTypes.add(sH);
+ hitTypes.add(dH);
+ MIPprocessor.registerHitTypes(hitTypes);
+ //
+ // Set the Number of Layers considered for MIP Seeds (Default 4)
+ // A minimum and a maximum allowed energy for seed-hits energy can be set
+ // (default: eMin = 0. and eMax = 1000.)
+ MIPprocessor.setNumberOfSeedLayers(int);
+ MIPprocessor.setMinmumEnergy(double);
+ MIPprocessor.setMaximumEnergy(double)
+ //
+ // Set Direction
+ // +1: Algorithm starts from the innermost Layer
+ // -1: Algorithm starts from the outermost layer
+ //
+ MIPprocessor.setDirectionAndFirstLayer(int newDir,int newFL);
+ //
+ // The User has the possibility to provide possible MIP starting points
+ //
+ MIPprocessor.provideNucleii(Vector<CalorimeterHit>);
+ //
+ // Print out some Debug messages
+ //
+ MIPprocessor.setDebugMode(boolean);
+ //
+ // Tell processor to either append (true) or replace (false,
+ // default) any possible existing list with the same name
+ //
+ MIPprocessor.setAppend(boolean);
+ //
+ // Add the MIPprocessor to the list of processors
+ //
+ add(MIPprocessor);
+ </pre></blockquote><p>
+ It generates a ClusterList of MIPClusters in the LCDEvent. Valid
+ argument for the constructor are <tt> EMCal</tt> and <tt> HCal </tt>
+ in order to read the standard EMCal and HCal CalorimeterHits
+ Objects. In addition, a tag <tt> User</tt> is provided that
+ allows the user to read in his own CalorimeterHits objects.
+ In the latter case, the <tt> setUserTag(string)</tt> has to be set
+ by the user in order to read the corresponding CalorimeterHits
+ Object from <tt> event</tt>.
+
+ @author [log in to unmask]
+ @version $Id: MIPClusterDriver.java,v 1.1 2006/01/02 21:45:19 mcharles Exp $
+
+ Modification Log:
+ -- 01/08/2005 Version 1.0 available in CVS
+ -- 08/08/2005 Bugfix -- Appending new and existing MIPClusterList
+ now works as expected.
+ -- 23/09/2005 Converted to org.lcsim by Mat
+*/
+
+public class MIPClusterDriver extends Driver{
+
+ /**
+ Constructor for MIPCluster processing -- valid Arguments are
+ "EMCal" and "HCal"
+ */
+ public MIPClusterDriver(String inString){
+
+ calType = inString;
+ if ( calType != "EMCal" && calType != "HCal" && calType != "User" ) {
+ throw new AssertionError("Wrong Calorimter Type Specified");
+ }
+
+ printInitialization();
+ }
+
+ private String calType = null; //"EMCal";
+ private String userTag = null;
+ private String clusterName = null;// = "MIPCluster "+calType;
+
+ private Vector<CalorimeterHit> nucleii = new Vector<CalorimeterHit>();
+ private boolean lUserNucleii = false;
+ public void provideNucleii(Vector<CalorimeterHit> v){
+ nucleii = v;
+ lUserNucleii = true;
+ }
+
+ public void process(EventHeader event)
+ {
+ // First, we have to get the list of calorimeter hits from
+ // the event header
+
+ List<CalorimeterHit> hits = null;
+
+ if ( calType == "EMCal" ) {
+ List<CalorimeterHit> barrelHits = event.get(CalorimeterHit.class, "EcalBarrHits");
+ List<CalorimeterHit> endcapHits = event.get(CalorimeterHit.class, "EcalEndcapHits");
+ hits = new Vector<CalorimeterHit>();
+ hits.addAll(barrelHits);
+ hits.addAll(endcapHits);
+ } else if ( calType == "HCal" ) {
+ List<CalorimeterHit> barrelHits = event.get(CalorimeterHit.class, "HcalBarrHits");
+ List<CalorimeterHit> endcapHits = event.get(CalorimeterHit.class, "HcalEndcapHits");
+ hits = new Vector<CalorimeterHit>();
+ hits.addAll(barrelHits);
+ hits.addAll(endcapHits);
+ } else if ( calType == "User" ) {
+ if ( userTag == null ) {
+ throw new AssertionError("No userTag Defined");
+ } else {
+ hits = event.get(CalorimeterHit.class, userTag);
+ }
+ }
+
+ // Now we need to make the cluster builder which we'll use for
+ // this event only:
+
+ MIPClusterBuilder clusterBuilder = new MIPClusterBuilder(hits, hitTypes);
+ clusterBuilder.setMinimumHitEnergy(eMin);
+ clusterBuilder.setMaximumHitEnergy(eMax);
+ clusterBuilder.setNumberOfSeedLayers(nSeedLayers);
+ clusterBuilder.setDirectionAndFirstLayer(direction,firstLayer);
+ if ( lUserNucleii ) {
+ clusterBuilder.provideNucleii(nucleii);
+ }
+ clusterBuilder.setDebugMode(lDebug);
+ clusterBuilder.initialize();
+
+ // Find the MIPs:
+
+ List<Cluster> clusters = clusterBuilder.getMIPClusterList();
+
+ // Write them out. We might want to append them, so check for that:
+
+ List<Cluster> outputList = null;
+ if (!lAppend) {
+ outputList = clusters;
+ } else {
+ outputList = event.get(Cluster.class, clusterName);
+ if (outputList == null) {
+ // Can't append because no list => make new one, then append
+ outputList = new Vector<Cluster>();
+ }
+ // Append
+ outputList.addAll(clusters);
+ }
+
+ int flags = 0; // What the hell are these magic flags for?
+ event.put(clusterName, outputList, Cluster.class, flags);
+ }
+
+ /**
+ Set name for ClusterList
+ */
+ public void setClusterName(String string){
+ clusterName = string;
+ System.out.println("ClusterName: "+clusterName);
+ }
+
+ /**
+ Set Tag for CalorimeterHits provided by user
+ */
+ public void setUserTag(String tag){
+ userTag = tag;
+ }
+
+ private void printInitialization(){
+ System.out.println("");
+ System.out.println("MIPClusterBuilder v1.0 "+calType);
+ System.out.println("----------------------");
+ }
+
+ private double eMin = 0.;
+ private double eMax = 1000.;
+ private int direction = 1;
+ private int firstLayer = 0;
+ private boolean lDebug = false;
+ private boolean lAppend = false;
+ private int nSeedLayers = 4;
+
+ public void setNumberOfSeedLayers(int n){
+ nSeedLayers = n;
+ }
+
+ public void setMinimumHitEnergy(double v){
+ eMin = v;
+ }
+ public void setMaximumHitEnergy(double v){
+ eMax = v;
+ }
+ public double getMinimumHitEnergy(){
+ return eMin;
+ }
+ public double getMaximumHitEnergy(){
+ return eMax;
+ }
+ public void setDirectionAndFirstLayer(int newDir, int newFL){
+ setDirection(newDir);
+ setFirstLayer(newFL);
+ }
+
+ private void setDirection(int i){
+ direction = i;
+ }
+ private void setFirstLayer(int i){
+ firstLayer = i;
+ }
+
+ public void setDebugMode(boolean b){
+ lDebug = b;
+ }
+ public void setAppend(boolean b){
+ lAppend = b;
+ }
+
+ private List<AbstractHitType> hitTypes;
+ public void registerHitTypes(List<AbstractHitType> hT){
+ hitTypes = hT;
+ }
+}
lcsim/src/org/lcsim/recon/cluster/mipfinder
diff -N SingleHit.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ SingleHit.java 2 Jan 2006 21:45:19 -0000 1.1
@@ -0,0 +1,61 @@
+package org.lcsim.recon.cluster.mipfinder;
+
+import org.lcsim.event.CalorimeterHit;
+import java.util.Vector;
+import org.lcsim.geometry.IDDecoder;
+import org.lcsim.geometry.CalorimeterIDDecoder;
+
+/**
+ Single Hit. Designed for use with
+ LCDG4 Geant files
+
+
+ @author Wolfgang F. Mader ([log in to unmask])
+ @version $Id: SingleHit.java,v 1.1 2006/01/02 21:45:19 mcharles Exp $
+
+ Modification Log:
+ -- 07/22/2004 Version 1.0
+ -- 09/26/2005 Converted to org.lcsim by Mat
+*/
+
+public class SingleHit extends AbstractHitType{
+//
+// Constructor Summary
+//
+ public SingleHit(){
+ identifier = "singleHit";
+
+ if ( lWelcome ){
+ System.out.println(identifier+" used in MIP reconstruction");
+ lWelcome = false;
+ }
+ }
+
+
+/**
+ * Check whether this hit is valid. For a SingleHit this means
+ * that there must be no neighbour hit (within 1 cell) in the same layer.
+ */
+ public boolean isValid(CalorimeterHit h,
+ HitCollection hc ){
+ boolean lSingle = true;
+
+ // Find all neighbouring cells:
+ int dLayer = 0;
+ int dU = 1;
+ int dV = 1;
+ CalorimeterIDDecoder id = (CalorimeterIDDecoder) h.getIDDecoder();
+ id.setID(h.getCellID());
+ long[] neighbours = id.getNeighbourIDs(dLayer, dU, dV);
+
+ for (int i=0; i<neighbours.length; i++ ) {
+ CalorimeterHit hit = hc.find(neighbours[i]);
+ if ( hit != null ){
+ // There is a bad neighbour => not a valid single hit.
+ lSingle = false;
+ }
+ }
+
+ return lSingle;
+ }
+}
CVSspam 0.2.8