Commit in GeomConverter/src/org/lcsim/detector/tracker/silicon on MAIN
ErrorEllipse2D.java+73added 1.1
SiSensor.java+469added 1.1
SiSensorElectrodes.java+47added 1.1
DopedSilicon.java+10-121.1 -> 1.2
TrackSegment.java+14-141.1 -> 1.2
SiStrips.java+109-131.1 -> 1.2
+722-39
3 added + 3 modified, total 6 files
Silicon strip simulation.  Refactored to support different electrode geometries (strips and pixels of various shapes).

GeomConverter/src/org/lcsim/detector/tracker/silicon
ErrorEllipse2D.java added at 1.1
diff -N ErrorEllipse2D.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ ErrorEllipse2D.java	19 Apr 2007 22:37:41 -0000	1.1
@@ -0,0 +1,73 @@
+/*
+ * ErrorEllipse2D.java
+ *
+ * Created on April 18, 2007, 3:08 PM
+ *
+ * To change this template, choose Tools | Template Manager
+ * and open the template in the editor.
+ */
+
+package org.lcsim.detector.tracker.silicon;
+
+import org.apache.commons.math.special.Erf;
+import org.apache.commons.math.MathException;
+
+/**
+ *
+ * @author tknelson
+ */
+public class ErrorEllipse2D
+{
+    // size and orientation of error ellipse
+    private double _major_axis;
+    private double _minor_axis;
+    private double _major_axis_angle;
+    
+    /** Creates a new instance of ErrorEllipse2D */
+    public ErrorEllipse2D()
+    {
+        // Unit circle by default
+        _major_axis = 1.0;
+        _minor_axis = 1.0;
+        _major_axis_angle = 0.0;
+    }
+    
+    public ErrorEllipse2D(double major_axis, double minor_axis, double major_axis_angle)
+    {
+        _major_axis = major_axis;
+        _minor_axis = minor_axis;
+        _major_axis_angle = major_axis_angle;
+    }
+    
+    public ErrorEllipse2D rotate(double rotation_angle)
+    {
+        _major_axis_angle += rotation_angle;
+        return this;
+    }
+    
+    public double erf1D(double integration_limit, double axis_angle)
+    {
+//        double angle_diff = axis_angle - _major_axis_angle;
+//        double sigma = Math.sqrt( Math.pow(_major_axis*Math.cos(angle_diff),2) + Math.pow(_minor_axis*Math.sin(angle_diff),2) );
+        
+        double erf = 0.0;
+        
+        try
+        {
+            erf = Erf.erf( integration_limit/sigma1D(axis_angle) );
+        }
+        catch (MathException no_convergence)
+        {
+            System.out.println("erf fails to converge!!");
+        }
+        return erf;        
+    }
+    
+    public double sigma1D(double axis_angle)
+    {
+        double angle_diff = axis_angle - _major_axis_angle;
+        return Math.sqrt( Math.pow(_major_axis*Math.cos(angle_diff),2) + Math.pow(_minor_axis*Math.sin(angle_diff),2) );
+    }
+    
+    
+}

GeomConverter/src/org/lcsim/detector/tracker/silicon
SiSensor.java added at 1.1
diff -N SiSensor.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ SiSensor.java	19 Apr 2007 22:37:41 -0000	1.1
@@ -0,0 +1,469 @@
+package org.lcsim.detector.tracker.silicon;
+/*
+ * SiSensor.java
+ *
+ * Created on July 20, 2005, 5:55 PM
+ *
+ * To change this template, choose Tools | Options and locate the template under
+ * the Source Creation and Management node. Right-click the template and choose
+ * Open. You can then make changes to the template in the Source Editor.
+ */
+
+import org.lcsim.detector.IDetectorElement;
+import org.lcsim.detector.DetectorElement;
+import org.lcsim.detector.IPhysicalVolumePath;
+import org.lcsim.detector.solids.Box;
+import org.lcsim.detector.Rotation3D;
+import org.lcsim.geometry.Detector;
+//import static org.lcsim.units.clhep.SystemOfUnits.*;
+//import static org.lcsim.units.clhep.PhysicalConstants.*;        
+
+import hep.physics.vec.Hep3Vector;
+import hep.physics.vec.BasicHep3Vector;
+import hep.physics.vec.VecOp;
+
+import java.util.*;
+
+/**
+ *
+ * @author tknelson
+ */
+public class SiSensor extends DetectorElement {
+    
+    // Enumerated types
+    //=================
+    public enum Orientation { PINSIDE, POUTSIDE };
+    
+    // Fields
+    //=======
+    // Static defaults - actual values user modifiable
+    private static Orientation _ORIENTATION_DEFAULT = Orientation.POUTSIDE;
+    private static double _DEPLETION_VOLTAGE_DEFAULT = 100;// * volt;
+    private static double _BIAS_VOLTAGE_DEFAULT = 110;// * volt;
+    
+    // Static parameters - not intended to be user modifiable
+    private static double _DEPOSITION_GRANULARITY = 0.05; // 5% of pitch
+    
+    // primary properties
+    //-------------------
+    
+    // Sensor ID
+    private int _sensorid;
+    
+    // electrodes, electrode angles and orientation of sensor
+    private Map<ChargeCarrier,SiSensorElectrodes> _electrodes = new EnumMap<ChargeCarrier,SiSensorElectrodes>(ChargeCarrier.class);
+    private Map<ChargeCarrier,Double> _electrode_angles = new EnumMap<ChargeCarrier,Double>(ChargeCarrier.class);
+    private Orientation _orientation;
+
+    // bulk - propoerties of the bulk
+    private DopedSilicon _bulk;
+    private double _thickness;  // accessed often, cached here for speed
+    
+    // operating point
+    private double _depletion_voltage;
+    private double _bias_voltage;
+    
+    // derived properties
+    //-------------------
+    // measured coordinate in local coordinates
+//    private EnumMap<ChargeCarrier,Hep3Vector> _measured_coordinate = new EnumMap<ChargeCarrier,Hep3Vector>(ChargeCarrier.class);
+    private EnumMap<ChargeCarrier,Hep3Vector[]> _measured_coordinates = new EnumMap<ChargeCarrier,Hep3Vector[]>(ChargeCarrier.class);
+    // strip direction in local coordinates
+//    private EnumMap<ChargeCarrier,Hep3Vector> _strip_direction = new EnumMap<ChargeCarrier,Hep3Vector>(ChargeCarrier.class);
+    // direction of Lorentz drift in local coordinates
+    private EnumMap<ChargeCarrier,Hep3Vector> _drift_direction = new EnumMap<ChargeCarrier,Hep3Vector>(ChargeCarrier.class);
+    // list of charge depostions to be distributed onto the electrodes
+    private List<TrackSegment> _track_list = new ArrayList<TrackSegment>();
+    
+    // Constructors
+    //=============
+    
+    // Default defines everything but electrode configuration
+    public SiSensor(
+            int sensorid,
+            String name,
+            IDetectorElement parent,
+            String support
+            )
+    {
+        super(name,parent,support);
+        setSensorID(sensorid);
+        setBulk(new DopedSilicon());
+        setDepletionVoltage(_DEPLETION_VOLTAGE_DEFAULT);
+        setBiasVoltage(_BIAS_VOLTAGE_DEFAULT);
+    }
+    
+    // Accessors
+    //==========
+    
+    // Setters
+    //--------
+    public void setSensorID(int sensorid)
+    {
+        _sensorid = sensorid;
+    }
+    
+    public void setElectrodes(ChargeCarrier carrier, SiSensorElectrodes electrodes)
+    {
+        _electrodes.put(carrier,electrodes);
+    }
+    
+    public void setElectrodeAngle(ChargeCarrier carrier, double electrode_angle)
+    {
+        _electrode_angles.put(carrier,electrode_angle);
+    }
+    
+    public void setOrientation(Orientation orientation)
+    {
+        _orientation = orientation;
+    }
+    
+    public void setBulk(DopedSilicon bulk)
+    {
+        _bulk = bulk;
+    }
+    
+    public void setDepletionVoltage(double depletion_voltage)
+    {
+        _depletion_voltage = depletion_voltage;
+    }
+    
+    public void setBiasVoltage(double bias_voltage)
+    {
+        _bias_voltage = bias_voltage;
+    }
+    
+    // Getters
+    public int getSensorID()
+    {
+        return _sensorid;
+    }    
+    
+    public SiSensorElectrodes getElectrodes(ChargeCarrier carrier)
+    {
+        return _electrodes.get(carrier);
+    }
+    
+    public double getElectrodeAngle(ChargeCarrier carrier)
+    {
+        return _electrode_angles.get(carrier);
+    }
+    
+    public Orientation getOrientation()
+    {
+        return _orientation;
+    }
+    
+    public DopedSilicon getBulk()
+    {
+        return _bulk;
+    }
+    
+    public double getThickness()
+    {
+        return _thickness;
+    }
+    
+    public double getDepletionVoltage()
+    {
+        return _depletion_voltage;
+    }
+    
+    public double getBiasVoltage()
+    {
+        return _bias_voltage;
+    }
+    
+    public Hep3Vector getBField(Hep3Vector local_position)
+    {
+        IDetectorElement ancestor = this.getParent();
+        while (!(ancestor instanceof Detector) && !(ancestor==null))
+        {
+            ancestor = ancestor.getParent();
+        }
+        
+        Hep3Vector global_position = getGeometry().getLocalToGlobal().transformed(local_position);
+        Hep3Vector field_global = ((Detector)ancestor).getFieldMap().getField(global_position);
+        
+        // FIXME - This is silly!!!!!
+        return VecOp.mult(getGeometry().getGlobalToLocal().getRotation().getRotationMatrix(),field_global);
+    }
+        
+    // Operators
+    //==========
+    private void initialize()
+    {
+        // Store various important directions
+        for (ChargeCarrier carrier : ChargeCarrier.values())
+        {
+            if (hasElectrodesOnSide(carrier)) {
+
+                // cache drift direction for electrodes on each side
+                _drift_direction.put(carrier,driftDirection(carrier, new BasicHep3Vector(0.0,0.0,0.0)));
+
+                // cache coordinates measured by the pattern of electrodes on each side
+                double electrode_angle = _electrode_angles.get(carrier);
+                int naxes = _electrodes.get(carrier).getNAxes();                
+                Hep3Vector[] measured_coordinates = new Hep3Vector[naxes];
+                
+                for (int iaxis = 1; iaxis < naxes ; iaxis++)
+                {
+                    measured_coordinates[iaxis] = measuredCoordinate(electrode_angle + iaxis*Math.PI/naxes);
+                }
+                _measured_coordinates.put(carrier,measured_coordinates);
+                
+                // strip direction... deprecated
+//                _strip_direction.put(carrier,stripDirection(electrode_angle));
+            }
+        }
+        // Cache thickness of bulk
+        _thickness = 2.0*((Box)getGeometry().getLogicalVolume().getSolid()).getZHalfLength();
+    }
+    
+    private double zOfSide(ChargeCarrier carrier)
+    {
+        if ( (carrier == ChargeCarrier.HOLE) == (_orientation == Orientation.POUTSIDE) ) return _thickness;
+        else return 0;
+    }
+    
+    private double distanceFromSide(Hep3Vector point, ChargeCarrier carrier)
+    {
+        return point.z() - zOfSide(carrier);
+    }
+    
+    private boolean hasElectrodesOnSide(ChargeCarrier carrier)
+    {
+        if(_electrodes.get(carrier) == null) return false;
+        else return true;
+    }
+    
+    private Hep3Vector driftVector(Hep3Vector origin, ChargeCarrier carrier)
+    {
+        double drift_vector_scale = distanceFromSide(origin,carrier)/_drift_direction.get(carrier).z();
+        return VecOp.mult(drift_vector_scale,_drift_direction.get(carrier));
+    }
+    
+    private Hep3Vector driftDestination(Hep3Vector origin, ChargeCarrier carrier)
+    {
+        return VecOp.add(origin,driftVector(origin, carrier));
+    }
+    
+    private ErrorEllipse2D diffusionEllipse(Hep3Vector point, ChargeCarrier carrier)
+    {
+        
+        // Common factors
+        double difference_V = _bias_voltage - _depletion_voltage;
+        double sum_V = _bias_voltage + _depletion_voltage;
+        double common_factor = 2.0*distanceFromSide(point,carrier)*_depletion_voltage/_thickness;
+
+        // Calculate charge spreading without magnetic field
+        double sigmasq = _bulk.K_BOLTZMANN * _bulk.getTemperature() * _thickness*_thickness / _depletion_voltage;
+        if (_bulk.isNtype() == (carrier==ChargeCarrier.HOLE))
+        {
+            sigmasq *= Math.log( sum_V / (sum_V - common_factor));
+        }
+        else
+        {
+            sigmasq *= Math.log( (difference_V + common_factor) / difference_V );
+        }
+        
+        double sigma = Math.sqrt(sigmasq);
+        
+        // Corrections for magnetic field -- this is an approximation, may have to be done better for high fields
+        double cos_theta_lorentz = VecOp.cosTheta(_drift_direction.get(carrier));
+        double phi_lorentz = VecOp.phi(_drift_direction.get(carrier));
+        double phi_electrode = _electrode_angles.get(carrier);
+        
+        double minor_axis = sigma*(1.0/cos_theta_lorentz); // drift time correction
+        double major_axis = minor_axis*(1.0/cos_theta_lorentz); // + drift angle correction
+        double phi_ellipse = -phi_electrode; // orientation of ellipse, relative to electrode coordinates
+        
+        // Create error ellipse
+        return new ErrorEllipse2D(major_axis, minor_axis, phi_ellipse);
+        
+    }
+    
+//    private double diffusionSigma(Hep3Vector point, ChargeCarrier carrier)
+//    {
+//        
+//        // Common factors
+//        double difference_V = _bias_voltage - _depletion_voltage;
+//        double sum_V = _bias_voltage + _depletion_voltage;
+//        double common_factor = 2.0*distanceFromSide(point,carrier)*_depletion_voltage/_thickness;
+//
+//        // Calculate charge spreading without magnetic field
+//        double sigmasq = k_Boltzmann * _bulk.getTemperature() * _thickness*_thickness / _depletion_voltage;
+//        if (_bulk.isNtype() == (carrier==ChargeCarrier.HOLE))
+//        {
+//            sigmasq *= Math.log( sum_V / (sum_V - common_factor));
+//        }
+//        else
+//        {
+//            sigmasq *= Math.log( (difference_V + common_factor) / difference_V );
+//        }
+//        
+//        double sigma = Math.sqrt(sigmasq);
+//        
+//        // Corrections for magnetic field -- this is an approximation, may have to be done better for high fields
+//        double cos_theta_lorentz_sq = Math.pow(VecOp.cosTheta(_drift_direction.get(carrier)),2);
+//        double phi_lorentz = VecOp.phi(_drift_direction.get(carrier));
+//        double phi_measured = VecOp.phi(_measured_coordinate.get(carrier));
+//        double cos_phi_diff_sq = Math.pow(Math.cos(phi_measured - phi_lorentz),2);
+//        
+//        sigma *= (1.0/cos_theta_lorentz_sq) *
+//                Math.sqrt(cos_theta_lorentz_sq + cos_phi_diff_sq - cos_theta_lorentz_sq*cos_phi_diff_sq);
+//        
+//        return sigma;
+//        
+//    }
+
+    private Hep3Vector measuredCoordinate(double electrode_angle)
+    {
+        return new BasicHep3Vector(Math.cos(electrode_angle),Math.sin(electrode_angle),0.0);
+    }
+    
+//    private Hep3Vector stripDirection(double strip_angle)
+//    {
+//        return measuredCoordinate(strip_angle + (Math.PI/2.0)) ;
+//    }
+    
+    private Hep3Vector driftDirection(ChargeCarrier carrier, Hep3Vector local_position)
+    {
+        double carrier_mobility = _bulk.mobility(carrier);        
+        Hep3Vector b_field = getBField(local_position);
+        
+        // Use magnetic field in plane of silicon to get total Lorentz angle
+        Hep3Vector b_planar = new BasicHep3Vector(b_field.x(), b_field.y(),0.0);
+        double bplanar_mag = b_planar.magnitude();
+        double tan_lorentz = _bulk.tanLorentzAngle(bplanar_mag, carrier);
+
+        // Drift direction in plane of silicon is direction of magnetic field in plane of silicon - PI/4
+        Hep3Vector drift_direction = 
+                VecOp.unit(new BasicHep3Vector(b_field.y(),-b_field.x(),bplanar_mag/tan_lorentz));
+
+        return drift_direction;
+        
+    }
+    
+    public void clearElectrodes()
+    {
+        for (ChargeCarrier carrier : ChargeCarrier.values())
+        {
+            if (hasElectrodesOnSide(carrier)) _electrodes.get(carrier).clear();
+        }
+    }
+    
+// Delta-ray code was deprecated in favor of letting GEANT do the work    
+//
+//    public void generateDeltaRays()
+//    {
+//        for (TrackSegment track : _track_list)
+//        {
+//            // Uncommitted standalone code exists to do this, which...
+//            // retrieves track from _track_list and calculates delta ray production
+//            // modifies original track in _track_list
+//            // adds delta rays to _track_list
+//        }
+//        return;
+//    }
+
+//    private int nSegments(TrackSegment track, ChargeCarrier carrier, double deposition_granularity)
+//    {
+//        // Decide how to cut track into pieces as a fraction of strip pitch
+//        if (!hasElectrodesOnSide(carrier)) return 0;
+//        Hep3Vector deposition_line = VecOp.sub( driftDestination(track.getP2(),carrier),
+//                driftDestination(track.getP1(),carrier) );
+//
+//        double projected_deposition_length = VecOp.dot(deposition_line,_measured_coordinate.get(carrier));
+//        
+//        return (int)Math.ceil(projected_deposition_length/(deposition_granularity*_electrodes.get(carrier).getPitch()));
+//    }
+
+    private int nSegments(TrackSegment track, ChargeCarrier carrier, double deposition_granularity)
+    {
+        // Decide how to cut track into pieces as a fraction of strip pitch        
+        int nsegments = 0;
+        if (!hasElectrodesOnSide(carrier)) return nsegments;
+        Hep3Vector deposition_line = VecOp.sub( driftDestination(track.getP2(),carrier),
+                driftDestination(track.getP1(),carrier) );
+       
+        int naxes = _electrodes.get(carrier).getNAxes();                        
+        for (int iaxis = 0; iaxis < naxes; iaxis++)
+        {
+            double projected_deposition_length = VecOp.dot(deposition_line,_measured_coordinates.get(carrier)[iaxis]);
+            int required_segments = (int)Math.ceil(projected_deposition_length/(deposition_granularity*_electrodes.get(carrier).getPitch(iaxis)));
+            nsegments = Math.max(nsegments,required_segments);
+        }   
+        return nsegments;
+    }
+    
+    
+//    private void depositCharge(double charge, Hep3Vector origin, ChargeCarrier carrier)
+//    {
+//        if (!hasStripsOnSide(carrier)) return;
+//        
+//        // find center of charge deposition
+//        double drift_destination = VecOp.dot( driftDestination(origin,carrier),
+//                _measured_coordinate.get(carrier) );
+//        double diffusion_sigma = diffusionSigma(origin,carrier);
+//        
+//        _electrodes.get(carrier).depositCharge(new BasicHep3Vector(drift_destination,0.0,0.0),charge,diffusion_sigma);
+//      
+//    }
+    
+    public void depositCharge()
+    {
+        
+        for (TrackSegment track : _track_list)
+        {
+            
+            // Decide how to cut track into pieces - use 5% of pitch
+            int nsegments = 0;
+            for (ChargeCarrier carrier : ChargeCarrier.values())
+            {
+                if (!hasElectrodesOnSide(carrier)) continue;
+                nsegments = Math.max(nsegments,nSegments(track,carrier, _DEPOSITION_GRANULARITY));
+            }
+            
+            // Set up segments
+            double segment_length = track.getLength()/nsegments;
+            double segment_charge = track.getEloss()/nsegments/_bulk.ENERGY_EHPAIR;
+            
+            Hep3Vector segment_step = VecOp.mult(segment_length,track.getDirection());
+            Hep3Vector segment_center = VecOp.add( track.getP1(),VecOp.mult(0.5,segment_step) );
+            
+            // Loop over segments
+            for (int iseg = 0; iseg < nsegments; iseg++)
+            {
+                // THROW POISSON WITH SEGMENT CHARGE?
+                
+                // loop over sides of detector
+                for (ChargeCarrier carrier : ChargeCarrier.values())
+                {
+                    if (hasElectrodesOnSide(carrier))
+                     {
+//                      depositCharge(segment_charge, segment_center, carrier);       
+ 
+                        // find center of charge deposition
+//                        double drift_destination = VecOp.dot( driftDestination(segment_center,carrier),_measured_coordinate.get(carrier) );
+//                        double diffusion_sigma = diffusionSigma(segment_center,carrier);
+//                        _electrodes.get(carrier).depositCharge(new BasicHep3Vector(drift_destination,0.0,0.0),segment_charge,diffusion_sigma);
+                        
+                        Rotation3D sensor_to_electrodes = new Rotation3D();
+                        sensor_to_electrodes.setPassiveXYZ(0.0,0.0,-_electrode_angles.get(carrier));
+                        
+                        Hep3Vector electrode_drift_destination = VecOp.mult(sensor_to_electrodes.getRotationMatrix(),driftDestination(segment_center,carrier));
+                        ErrorEllipse2D electrode_charge_distribution = diffusionEllipse(segment_center,carrier).rotate(-_electrode_angles.get(carrier));
+                       _electrodes.get(carrier).depositCharge(segment_charge,electrode_drift_destination,electrode_charge_distribution);
+                    }
+                }
+                
+                // step to next segment
+                segment_center = VecOp.add(segment_center, segment_step);
+            }
+              
+        }
+
+    }
+    
+}

GeomConverter/src/org/lcsim/detector/tracker/silicon
SiSensorElectrodes.java added at 1.1
diff -N SiSensorElectrodes.java
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ SiSensorElectrodes.java	19 Apr 2007 22:37:41 -0000	1.1
@@ -0,0 +1,47 @@
+/*
+ * SiSensorElectrodes.java
+ *
+ * Created on April 11, 2007, 9:14 PM
+ *
+ * To change this template, choose Tools | Template Manager
+ * and open the template in the editor.
+ */
+
+package org.lcsim.detector.tracker.silicon;
+
+import hep.physics.vec.Hep3Vector;
+
+/**
+ *
+ * @author tknelson
+ */
+public interface SiSensorElectrodes
+{
+    // Cell shape, assumed to be a polygon with an even number of sides (1=strip, 2=rectagular pixel, 3=hexagon, etc...)
+    public int getNAxes();
+    
+    // Number of cells (strips or pixels)
+    public int getNCells();
+    
+    // Number of cells along each axis
+    public int getNCells(int direction);
+    
+    // Size of a cell (strip or pixel pitch)
+    public double getPitch(int direction);
+    
+    // Position of a particular cell (by cell number)
+    public Hep3Vector getCellPosition(int cell_id);
+    
+    // ID of cell at a given position (cell number)
+    public int getCellID(Hep3Vector position);
+    
+    // Location of given position within a cell
+    public Hep3Vector getPositionInCell(Hep3Vector position);
+    
+    // Deposit Gaussian-distributed charge on electrodes
+//    public void depositCharge(Hep3Vector position, double charge, double sigma);
+    public void depositCharge(double charge, Hep3Vector position, ErrorEllipse2D distribution);
+    
+    // Clear charge from electrodes
+    public void clear();
+}

GeomConverter/src/org/lcsim/detector/tracker/silicon
DopedSilicon.java 1.1 -> 1.2
diff -u -r1.1 -r1.2
--- DopedSilicon.java	10 Apr 2007 19:27:44 -0000	1.1
+++ DopedSilicon.java	19 Apr 2007 22:37:41 -0000	1.2
@@ -9,8 +9,8 @@
  * Open. You can then make changes to the template in the Source Editor.
  */
 
-import static org.lcsim.units.clhep.SystemOfUnits.*;
-import static org.lcsim.units.clhep.PhysicalConstants.*;
+//import static org.lcsim.units.clhep.SystemOfUnits.*;
+//import static org.lcsim.units.clhep.PhysicalConstants.*;
 import java.util.*;
 
 /**
@@ -24,22 +24,20 @@
     //=======
     
     // Static
-    //static public double K_BOLTZMANN = 8.617385E-5; // eV/degK
-    //static public double E_PAIR = 3.62E-9; // 3.6E-9 GeV/e-h pair
-    static public double ENERGY_EHPAIR = 3.62 * eV;
-    
+    static public double K_BOLTZMANN = 8.617385E-5; // eV/degK
+    static public double ENERGY_EHPAIR = 3.62E-9; // 3.62E-9 GeV/e-h pair
     
     // Member
-    private double _temperature = 293.0 * kelvin;
-    private double _doping_concentration = 6.0E+11 / cm3; 
+    private double _temperature = 293.0; // * kelvin;
+    private double _doping_concentration = 6.0E+11; // / cm3; 
     private EnumMap<ChargeCarrier,Double> _carrier_concentration = new EnumMap<ChargeCarrier,Double>(ChargeCarrier.class);    
     
     // Constructors
     //=============
     public DopedSilicon()
     {
-        setElectronConcentration(1.0E+14 / cm3);
-        setHoleConcentration(1.0E+14 / cm3);
+        setElectronConcentration(1.0E+14);
+        setHoleConcentration(1.0E+14);
     }
 
     // Setters/Accessors
@@ -70,7 +68,7 @@
     // Lorentz angle calculation for silicon sensors
     public double tanLorentzAngle(double b_field, ChargeCarrier charge_carrier)
     {
-        return b_field * mobility(charge_carrier);// * 1.0E-4; // (must clean up units)
+        return b_field * mobility(charge_carrier) * 1.0E-4; // (must clean up units)
     }
     
     // Mobility calculation with correction for irradiated sensors
@@ -78,7 +76,7 @@
     {
         return charge_carrier.muMin(_temperature) + charge_carrier.mu0(_temperature) / 
                 (1.0 + Math.pow(_carrier_concentration.get(charge_carrier)/charge_carrier.nRef(_temperature), 
-                                charge_carrier.alpha(_temperature))) * cm2/(volt*s);
+                                charge_carrier.alpha(_temperature)));
     }
 
     // Silicon type

GeomConverter/src/org/lcsim/detector/tracker/silicon
TrackSegment.java 1.1 -> 1.2
diff -u -r1.1 -r1.2
--- TrackSegment.java	10 Apr 2007 19:27:44 -0000	1.1
+++ TrackSegment.java	19 Apr 2007 22:37:41 -0000	1.2
@@ -99,19 +99,19 @@
         return _energy_loss/getLength();
     }
     
-    public void rotateMedium(Hep3Vector axis, double center, double angle)
-    {           
-        double old_length = getLength();
-        rotateMedium(_p1,axis,center,angle);
-        rotateMedium(_p2,axis,center,angle);
-        _energy_loss *= getLength()/old_length;        
-    }
-    
-    private void rotateMedium(Hep3Vector point, Hep3Vector axis, double center, double angle)
-    {
-        assert (axis.z() == 0.0); // assumed that we are rotating silicon z-planes        
-        point = VecOp.add(point,VecOp.mult(Math.tan(angle)*(center - point.z()),
-                VecOp.unit(VecOp.cross(axis, new BasicHep3Vector(0,0,1)))));
-    }
+//    public void rotateMedium(Hep3Vector axis, double center, double angle)
+//    {           
+//        double old_length = getLength();
+//        rotateMedium(_p1,axis,center,angle);
+//        rotateMedium(_p2,axis,center,angle);
+//        _energy_loss *= getLength()/old_length;        
+//    }
+//    
+//    private void rotateMedium(Hep3Vector point, Hep3Vector axis, double center, double angle)
+//    {
+//        assert (axis.z() == 0.0); // assumed that we are rotating silicon z-planes        
+//        point = VecOp.add(point,VecOp.mult(Math.tan(angle)*(center - point.z()),
+//                VecOp.unit(VecOp.cross(axis, new BasicHep3Vector(0,0,1)))));
+//    }
     
 }

GeomConverter/src/org/lcsim/detector/tracker/silicon
SiStrips.java 1.1 -> 1.2
diff -u -r1.1 -r1.2
--- SiStrips.java	10 Apr 2007 19:27:44 -0000	1.1
+++ SiStrips.java	19 Apr 2007 22:37:41 -0000	1.2
@@ -9,6 +9,12 @@
  * Open. You can then make changes to the template in the Source Editor.
  */
 
+//import static org.lcsim.units.clhep.SystemOfUnits.*;
+import hep.physics.vec.Hep3Vector;
+import hep.physics.vec.BasicHep3Vector;
+import hep.physics.vec.VecOp;
+import org.apache.commons.math.special.Erf;
+import org.apache.commons.math.MathException;
 import java.util.SortedMap;
 import java.util.TreeMap;
 
@@ -16,9 +22,10 @@
  *
  * @author tknelson
  */
-public class SiStrips
+public class SiStrips implements SiSensorElectrodes
 {
-    
+
+    // Fields
     private int _nstrips; // number of strips
     private double _pitch; // sense pitch
     private int _floating_strips; // number of floating strips between readout strips
@@ -38,6 +45,7 @@
     
     // Constructors
     //=============
+    
     public SiStrips(int nstrips, double pitch, int floating_strips)
     {
         setNStrips(nstrips);
@@ -100,38 +108,126 @@
     
     // Operators
     //==========
-    public int baseStrip(double position)
+    public int getNAxes()
     {
-        return (int)Math.floor(position/_pitch);
+        return 1;
     }
     
-    public double interstripPosition(double position)
+    public int getNCells()
     {
-        return position - baseStrip(position)*_pitch;
+        return _nstrips;
     }
-   
-    public double stripPosition(int strip_number)
+    
+    public int getNCells(int direction)
     {
-        return strip_number*_pitch;
+        if (direction == 0)
+        {
+            return _nstrips;
+        }
+        else return 1;
     }
     
-    public double stripPosition(double strip_coordinate)
+    public double getPitch(int direction)
     {
-        return strip_coordinate*_pitch;
+        return _pitch;
     }
     
-    public void clear()
+    public int getCellID(Hep3Vector position)
     {
-       _strip_charge.clear();
+        return (int)Math.floor(position.x()/_pitch);
     }
     
+    public Hep3Vector getPositionInCell(Hep3Vector position)
+    {
+        return VecOp.add(position,new BasicHep3Vector(-getCellID(position)*_pitch, 0.0, 0.0));
+    }
+   
+    public Hep3Vector getCellPosition(int strip_number)
+    {
+        return new BasicHep3Vector(strip_number*_pitch,0.0,0.0);
+    }
+    
+//    public double stripPosition(double strip_coordinate)
+//    {
+//        return strip_coordinate*_pitch;
+//    }    
+    
+//    public void depositCharge(Hep3Vector position, double charge, double sigma)
+//    {
+//        int base_strip = getCellID(position);
+//        Hep3Vector interstrip_position = getPositionInCell(position);
+//        
+//        // put charge on strips in window 3-sigma strips on each side of base strip
+//        double pitch = getPitch(1);
+//
+//        int window_size = (int)Math.ceil(3.0*sigma/pitch);
+//        
+//        double erf_min = 1.0;
+//        double erf_max = 1.0;
+//        for (int istrip = base_strip-window_size; istrip <= base_strip+window_size; istrip++)
+//        {
+//            
+//            try
+//            {
+//                erf_max = Erf.erf( (_electrodes.get(carrier).stripPosition(istrip+0.5) - drift_destination)/diffusion_sigma );
+//            }
+//            catch (MathException no_convergence)
+//            {
+//                System.out.println("erf fails to converge!!");
+//            }
+//            
+//            int strip_charge = (int)Math.round( (erf_min-erf_max) * charge );
+//            addCharge(istrip,strip_charge);
+//            
+//            erf_min = erf_max;
+//        }                  
+//        return;
+//    }
+    
+    
+    public void depositCharge(double charge, Hep3Vector position, ErrorEllipse2D distribution)
+    {
+        int base_strip = getCellID(position);
+        Hep3Vector interstrip_position = getPositionInCell(position);
+       
+        // put charge on strips in window 3-sigma strips on each side of base strip
+        double pitch = getPitch(1);
+        double axis_angle = 0.0;
+
+        int window_size = (int)Math.ceil(3.0*distribution.sigma1D(axis_angle)/pitch);
+        
+        double erf_lower = 1.0;
+        double erf_upper = 1.0;
+    
+        for (int istrip = base_strip-window_size; istrip <= base_strip+window_size; istrip++)
+        {
+            double cell_edge_upper = getCellPosition(istrip).x() + pitch/2.0;
+            erf_upper = distribution.erf1D(cell_edge_upper,axis_angle);
+
+            int strip_charge = (int)Math.round( (erf_lower-erf_upper) * charge); 
+            addCharge(istrip,strip_charge);
+            
+            erf_lower = erf_upper;
+            
+        }
+        return;
+    }
+    
+    
     public void addCharge(int strip, double charge)
     { 
         if (_strip_charge.containsKey(strip)) {
             charge += _strip_charge.get(strip);            
         }   
         _strip_charge.put(strip,charge);
+    }    
+    
+    public void clear()
+    {
+       _strip_charge.clear();
     }
+
+
     
 //    public void generateReadout()
 //    {
CVSspam 0.2.8