GeomConverter/src/org/lcsim/detector/tracker/silicon
diff -N SiStripSensor.java
--- SiStripSensor.java 10 Apr 2007 19:27:44 -0000 1.1
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,395 +0,0 @@
-package org.lcsim.detector.tracker.silicon;
-/*
- * SiStripDetector.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.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 org.apache.commons.math.special.Erf;
-import org.apache.commons.math.MathException;
-
-import java.util.*;
-
-/**
- *
- * @author tknelson
- */
-public class SiStripSensor extends DetectorElement {
-
- // Enumerated types
- //=================
- protected enum Orientation { PINSIDE, POUTSIDE };
-
- // Fields
- //=======
-
- // parameters - not intended to be user modifiable
- private static double _DEPOSITION_GRANULARITY = 0.05 * mm;
- private static double _DEFAULT_DEPLETION_VOLTAGE = 100 * volt;
- private static double _DEFAULT_BIAS_VOLTAGE = 110.0 * volt;
-
- // primary properties
- //-------------------
- // strips, strip angles and orientation of sensor
- private Map<ChargeCarrier,SiStrips> _strips = new EnumMap<ChargeCarrier,SiStrips>(ChargeCarrier.class);
- private Map<ChargeCarrier,Double> _strip_angles = new EnumMap<ChargeCarrier,Double>(ChargeCarrier.class);
- private Orientation _orientation = Orientation.POUTSIDE;
-
- // bulk - propoerties of the bulk
- private DopedSilicon _bulk = new DopedSilicon();
- private double _thickness; // accessed often, cached here for speed
- private double _inactive_width;
-
- // 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);
- // 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 strips
- private List<TrackSegment> _track_list = new ArrayList<TrackSegment>();
-
- // Constructors
- //=============
-
- // Default, 300 micron, p-in-n silicon; 0-degree, 50 micron single-sided readout with one floating strip
- public SiStripSensor(
- String name,
- IDetectorElement parent,
- IPhysicalVolumePath support,
- int nstrips, double pitch, int floating_strips)
- {
- super(name,parent,support);
- setStrips(ChargeCarrier.HOLE, new SiStrips(nstrips,pitch,floating_strips));
- setStripAngle(ChargeCarrier.HOLE, 0.0);
- setBulk(new DopedSilicon());
- setDepletionVoltage(_DEFAULT_DEPLETION_VOLTAGE);
- setBiasVoltage(_DEFAULT_BIAS_VOLTAGE);
- initialize();
- }
-
- // Accessors
- //==========
-
- // Setters
- //--------
-
- public void setStrips(ChargeCarrier carrier, SiStrips strips)
- {
- _strips.put(carrier,strips);
- }
-
- public void setStripAngle(ChargeCarrier carrier, double strip_angle)
- {
- _strip_angles.put(carrier,strip_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 SiStrips getStrips(ChargeCarrier carrier)
- {
- return _strips.get(carrier);
- }
-
- public double getStripAngle(ChargeCarrier carrier)
- {
- return _strip_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().getGlobalToLocal().transformed(local_position);
- return new BasicHep3Vector(((Detector)ancestor).getFieldMap().getField(global_position.v()));
- }
-
- // Operators
- //==========
- private void initialize()
- {
- // Store various important directions
- for (ChargeCarrier carrier : ChargeCarrier.values())
- {
- if (hasStripsOnSide(carrier)) {
- _drift_direction.put(carrier,driftDirection(carrier, new BasicHep3Vector(0.0,0.0,0.0)));
- double strip_angle = _strip_angles.get(carrier);
- _measured_coordinate.put(carrier,measuredCoordinate(strip_angle));
- _strip_direction.put(carrier,stripDirection(strip_angle));
- }
- }
- // Cache thickness
- _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 hasStripsOnSide(ChargeCarrier carrier)
- {
- if (_strips.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 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
- 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 strip_angle)
- {
- return new BasicHep3Vector(Math.cos(strip_angle),Math.sin(strip_angle),0.0);
- }
-
- private Hep3Vector stripDirection(double strip_angle)
- {
- return measuredCoordinate(strip_angle + (Math.PI/4.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 clearStrips()
- {
- for (ChargeCarrier carrier : ChargeCarrier.values())
- {
- if (hasStripsOnSide(carrier)) _strips.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 (!hasStripsOnSide(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*_strips.get(carrier).getPitch()));
- }
-
- 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) );
- int base_strip = _strips.get(carrier).baseStrip(drift_destination);
- double interstrip_position = _strips.get(carrier).interstripPosition(drift_destination);
-
- // put charge on strips in window 3-sigma strips on each side of base strip
- double pitch = _strips.get(carrier).getPitch();
- double diffusion_sigma = diffusionSigma(origin,carrier);
- int window_size = (int)Math.ceil(3.0*diffusion_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( (_strips.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 );
- _strips.get(carrier).addCharge(istrip,strip_charge);
-
- erf_min = erf_max;
- }
- }
-
- 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 (!hasStripsOnSide(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 (!hasStripsOnSide(carrier)) continue;
- depositCharge(segment_charge, segment_center, carrier);
- }
-
- // step to next segment
- segment_center = VecOp.add(segment_center, segment_step);
- }
-
- }
-
- }
-
-}