lcsim/src/org/lcsim/contrib/SiStripSim
diff -N ClusterMaker.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ ClusterMaker.java 6 Nov 2007 20:06:33 -0000 1.1
@@ -0,0 +1,23 @@
+/*
+ * ClusterMaker.java
+ *
+ * Created on September 26, 2007, 1:57 PM
+ *
+ * To change this template, choose Tools | Template Manager
+ * and open the template in the editor.
+ */
+
+package org.lcsim.contrib.SiStripSim;
+
+import org.lcsim.event.RawTrackerHit;
+import org.lcsim.event.TrackerHit;
+import java.util.List;
+
+/**
+ *
+ * @author tknelson
+ */
+public interface ClusterMaker
+{
+ List<TrackerHit> makeClusters(List<RawTrackerHit> raw_hits);
+}
lcsim/src/org/lcsim/contrib/SiStripSim
diff -N StripClusterMaker.java
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ StripClusterMaker.java 6 Nov 2007 20:06:33 -0000 1.1
@@ -0,0 +1,285 @@
+/*
+ * StripClusterMaker.java
+ *
+ * Created on September 26, 2007, 1:57 PM
+ *
+ * To change this template, choose Tools | Template Manager
+ * and open the template in the editor.
+ */
+
+package org.lcsim.contrib.SiStripSim;
+
+import hep.physics.matrix.Matrix;
+import hep.physics.matrix.SymmetricMatrix;
+import hep.physics.vec.BasicHep3Matrix;
+import hep.physics.vec.BasicHep3Vector;
+import hep.physics.vec.Hep3Vector;
+import hep.physics.vec.VecOp;
+import org.lcsim.event.RawTrackerHit;
+import org.lcsim.event.TrackerHit;
+import org.lcsim.detector.identifier.IExpandedIdentifier;
+import org.lcsim.detector.identifier.ExpandedIdentifier;
+import org.lcsim.detector.identifier.IIdentifierDictionary.FieldNotFoundException;
+
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Set;
+import org.lcsim.detector.tracker.silicon.ChargeCarrier;
+import org.lcsim.detector.tracker.silicon.DopedSilicon;
+import org.lcsim.detector.tracker.silicon.SiSensor;
+import org.lcsim.detector.tracker.silicon.SiSensorElectrodes;
+import org.lcsim.event.SimTrackerHit;
+import org.lcsim.event.base.BaseTrackerHitMC;
+
+/**
+ *
+ * @author tknelson
+ */
+public class StripClusterMaker implements ClusterMaker
+{
+ int _seed_threshold = 4;
+ int _neighbor_threshold = 2;
+ int _cluster_threshold = 3;
+
+ // Temporary maps connecting electrodes to hit list, hits to strip number, electrode ID to electrodes
+ // (the last should be cached... not a model of efficiency at the moment)
+ Map<IExpandedIdentifier,List<RawTrackerHit>> _hit_map = new HashMap<IExpandedIdentifier,List<RawTrackerHit>>();
+ Map<RawTrackerHit,Integer> _strip_map = new HashMap<RawTrackerHit,Integer>();
+ Map<IExpandedIdentifier,SiSensorElectrodes> _electrode_map = new HashMap<IExpandedIdentifier,SiSensorElectrodes>();
+
+ /** Creates a new instance of StripClusterMaker */
+ public StripClusterMaker()
+ {
+
+ }
+
+ public List<TrackerHit> makeClusters(List<RawTrackerHit> raw_hits)
+ {
+
+ // clear the maps
+ _hit_map.clear();
+ _strip_map.clear();
+ _electrode_map.clear();
+
+ List<TrackerHit> clusters = new ArrayList<TrackerHit>();
+
+// Map<IExpandedIdentifier,List<RawTrackerHit>> hit_map = new HashMap<IExpandedIdentifier,List<RawTrackerHit>>();
+// Map<IExpandedIdentifier,SiSensorElectrodes> electrode_map = new HashMap<IExpandedIdentifier,SiSensorElectrodes>();
+// Map<RawTrackerHit,Integer> strip_map = new HashMap<RawTrackerHit,Integer>();
+
+ // Sort RawTrackerHits by electrodes
+ for (RawTrackerHit raw_hit : raw_hits)
+ {
+ int strip_field;
+ try
+ {
+ strip_field = raw_hit.getIdentifierHelper().getFieldIndex("strip");
+ }
+ catch (FieldNotFoundException exception)
+ {
+ throw new RuntimeException(exception);
+ }
+ int side_field;
+ try
+ {
+ side_field = raw_hit.getIdentifierHelper().getFieldIndex("side");
+ }
+ catch (FieldNotFoundException exception)
+ {
+ throw new RuntimeException(exception);
+ }
+
+ // Get expanded ID
+ IExpandedIdentifier id = new ExpandedIdentifier(raw_hit.getExpandedIdentifier());
+
+ // Get strip number
+ int strip_id = id.getValue(strip_field);
+ _strip_map.put(raw_hit,strip_id);
+
+ // Get side of sensor
+ ChargeCarrier carrier;
+ if (id.getValue(side_field) == 1)
+ {
+ carrier = ChargeCarrier.HOLE;
+ }
+ else if (id.getValue(side_field) == -1)
+ {
+ carrier = ChargeCarrier.ELECTRON;
+ }
+ else
+ {
+ throw new RuntimeException("Invalid side field in RawTrackerHit.");
+ }
+
+ // Zero strip number to refer only to electrode set
+ id.setValue(strip_field,0);
+
+ // Fill maps needed for clustering
+ if (_electrode_map.get(id) == null)
+ {
+ _electrode_map.put(id,((SiSensor)raw_hit.getDetectorElement()).getReadoutElectrodes(carrier));
+ _hit_map.put(id,new ArrayList<RawTrackerHit>());
+ }
+ _hit_map.get(id).add(raw_hit);
+
+ }
+
+ // Do clustering for each set of electrodes
+ for (IExpandedIdentifier electrodes_id : _electrode_map.keySet())
+ {
+
+ List<RawTrackerHit> hits = _hit_map.get(electrodes_id);
+ List<RawTrackerHit> unclustered_hits = new ArrayList<RawTrackerHit>(hits);
+ SiSensorElectrodes electrodes = _electrode_map.get(electrodes_id);
+
+ for (RawTrackerHit hit : hits)
+ {
+
+ Kpix.ControlRegisters control_registers = Kpix.ControlRegisters.decoded(hit.getADCValues()[0]);
+ Kpix.KpixChannel.ReadoutRegisters readout_registers = Kpix.KpixChannel.ReadoutRegisters.decoded(hit.getADCValues()[1]);
+ double noise = Kpix.KpixChannel.computeNoise(10.0); // FIXME: should get this information from the electrodes.
+ double signal = Kpix.computeCharge(readout_registers, control_registers);
+
+ if (signal/noise > _seed_threshold && unclustered_hits.contains(hit))
+ {
+ List<RawTrackerHit> cluster = new ArrayList<RawTrackerHit>();
+ List<RawTrackerHit> clustered_hits = new ArrayList<RawTrackerHit>();
+
+ clustered_hits.add(hit);
+
+ while (clustered_hits.size() != 0)
+ {
+ cluster.addAll(clustered_hits);
+ unclustered_hits.removeAll(clustered_hits);
+ clustered_hits = neighborHits(clustered_hits,unclustered_hits,electrodes);
+ }
+
+ // now make a cluster or trackerhit
+ clusters.add(makeTrackerHit(cluster,electrodes));
+
+ }
+ }
+
+
+ }
+
+ return clusters;
+
+ }
+
+ private List<RawTrackerHit> neighborHits(List<RawTrackerHit> clustered_hits, List<RawTrackerHit> unclustered_hits,
+ SiSensorElectrodes electrodes)
+ {
+ List<RawTrackerHit> neighbor_hits = new ArrayList<RawTrackerHit>();
+
+ for (RawTrackerHit seed_hit : clustered_hits)
+ {
+ Set<Integer> neighbor_cells = electrodes.getNearestNeighborCells(_strip_map.get(seed_hit));
+ for (RawTrackerHit hit : unclustered_hits)
+ {
+
+ Kpix.ControlRegisters control_registers = Kpix.ControlRegisters.decoded(hit.getADCValues()[0]);
+ Kpix.KpixChannel.ReadoutRegisters readout_registers = Kpix.KpixChannel.ReadoutRegisters.decoded(hit.getADCValues()[1]);
+ double noise = Kpix.KpixChannel.computeNoise(10.0); // FIXME: should get this information from the electrodes.
+ double signal = Kpix.computeCharge(readout_registers, control_registers);
+
+ if (neighbor_cells.contains(_strip_map.get(hit)) && signal/noise > _neighbor_threshold)
+ {
+ neighbor_hits.add(hit);
+ }
+ }
+ }
+ return neighbor_hits;
+ }
+
+ private TrackerHit makeTrackerHit(List<RawTrackerHit> cluster, SiSensorElectrodes electrodes)
+ {
+ double[] position = getPosition(cluster,electrodes);
+ SymmetricMatrix covariance = getCovariance(cluster,electrodes);
+ double time = getTime(cluster);
+ double energy = getEnergy(cluster);
+ int type = 0;
+
+ TrackerHit hit = new BaseTrackerHitMC(position, covariance.asPackedArray(true), time, energy, type, getSimulatedHits(cluster));
+ return hit;
+ }
+
+ private List<SimTrackerHit> getSimulatedHits(List<RawTrackerHit> cluster)
+ {
+ Set<SimTrackerHit> simulated_hits = new HashSet<SimTrackerHit>();
+ for (RawTrackerHit hit : cluster)
+ {
+ simulated_hits.addAll(hit.getSimTrackerHit());
+ }
+ return new ArrayList<SimTrackerHit>(simulated_hits);
+ }
+
+ private double[] getPosition(List<RawTrackerHit> cluster, SiSensorElectrodes electrodes)
+ {
+ double total_charge = 0;
+ Hep3Vector position = new BasicHep3Vector(0,0,0);
+
+ for (RawTrackerHit hit : cluster)
+ {
+ Kpix.ControlRegisters control_registers = Kpix.ControlRegisters.decoded(hit.getADCValues()[0]);
+ Kpix.KpixChannel.ReadoutRegisters readout_registers = Kpix.KpixChannel.ReadoutRegisters.decoded(hit.getADCValues()[1]);
+ double signal = Kpix.computeCharge(readout_registers, control_registers);
+
+ total_charge += signal;
+ position = VecOp.add(position,VecOp.mult(signal,electrodes.getCellPosition(_strip_map.get(hit))));
+ }
+ position = VecOp.mult(1/total_charge,position);
+
+ return electrodes.getLocalToGlobal().transformed(position).v();
+ }
+
+ private double getTime(List<RawTrackerHit> cluster)
+ {
+ int time_sum = 0;
+ int signal_sum = 0;
+
+ for (RawTrackerHit hit : cluster)
+ {
+ Kpix.ControlRegisters control_registers = Kpix.ControlRegisters.decoded(hit.getADCValues()[0]);
+ Kpix.KpixChannel.ReadoutRegisters readout_registers = Kpix.KpixChannel.ReadoutRegisters.decoded(hit.getADCValues()[1]);
+ double signal = Kpix.computeCharge(readout_registers, control_registers);
+ double time = readout_registers.getTime();
+
+ time_sum += time_sum * signal;
+ signal_sum += signal_sum;
+
+ }
+ return (double)time_sum/(double)signal_sum;
+ }
+
+ private SymmetricMatrix getCovariance(List<RawTrackerHit> cluster, SiSensorElectrodes electrodes)
+ {
+ // FIXME: very raw hack
+
+ BasicHep3Matrix covariance = new BasicHep3Matrix();
+ covariance.setElement(0,0,Math.pow(0.007,2));
+ covariance.setElement(1,1,Math.pow(93.031/Math.sqrt(12),2));
+ covariance.setElement(2,2,0.0);
+ VecOp.mult(electrodes.getLocalToGlobal().getRotation().getRotationMatrix(),covariance);
+ return new SymmetricMatrix((Matrix)covariance);
+ }
+
+ private double getEnergy(List<RawTrackerHit> cluster)
+ {
+ double total_charge = 0.0;
+ for (RawTrackerHit hit : cluster)
+ {
+ Kpix.ControlRegisters control_registers = Kpix.ControlRegisters.decoded(hit.getADCValues()[0]);
+ Kpix.KpixChannel.ReadoutRegisters readout_registers = Kpix.KpixChannel.ReadoutRegisters.decoded(hit.getADCValues()[1]);
+ double signal = Kpix.computeCharge(readout_registers, control_registers);
+
+ total_charge += signal;
+ }
+ return total_charge * DopedSilicon.ENERGY_EHPAIR;
+ }
+
+
+}