View Javadoc

1   package org.lcsim.detector.tracker.silicon;
2   /*
3    * SiSensor.java
4    *
5    * Created on July 20, 2005, 5:55 PM
6    *
7    * To change this template, choose Tools | Options and locate the template under
8    * the Source Creation and Management node. Right-click the template and choose
9    * Open. You can then make changes to the template in the Source Editor.
10   */
11  
12  import hep.physics.matrix.BasicMatrix;
13  import hep.physics.vec.Hep3Vector;
14  import hep.physics.vec.VecOp;
15  import java.util.Collection;
16  
17  import java.util.EnumMap;
18  import java.util.Map;
19  
20  import org.lcsim.detector.DetectorElement;
21  import org.lcsim.detector.IDetectorElement;
22  import org.lcsim.detector.converter.compact.DeDetector;
23  import org.lcsim.detector.identifier.ExpandedIdentifier;
24  import org.lcsim.detector.identifier.IExpandedIdentifier;
25  import org.lcsim.detector.identifier.IIdentifier;
26  import org.lcsim.detector.identifier.IIdentifierDictionary;
27  import org.lcsim.detector.identifier.IIdentifierHelper;
28  import org.lcsim.detector.solids.GeomOp3D;
29  import org.lcsim.detector.solids.Point3D;
30  import org.lcsim.detector.solids.Polygon3D;
31  
32  /**
33   *
34   * @author tknelson
35   */
36  public class SiSensor extends DetectorElement
37  {
38      
39      // Enumerated types
40      //=================
41      
42      // Fields
43      //=======
44      // Static defaults - actual values user modifiable
45      private static double _DEPLETION_VOLTAGE_DEFAULT = 100;// * volt;
46      private static double _BIAS_VOLTAGE_DEFAULT = 110;// * volt;
47      
48      // primary properties
49      //-------------------
50      
51      // Sensor ID
52      private int _sensorid;
53      
54      // biasing and electrodes
55      private Map<ChargeCarrier, Polygon3D> _bias_surfaces = new EnumMap<ChargeCarrier,Polygon3D>(ChargeCarrier.class);
56      private Map<ChargeCarrier, SiSensorElectrodes> _sense_electrodes = new EnumMap<ChargeCarrier,SiSensorElectrodes>(ChargeCarrier.class);
57      private Map<ChargeCarrier, SiSensorElectrodes> _readout_electrodes = new EnumMap<ChargeCarrier,SiSensorElectrodes>(ChargeCarrier.class);
58      private Map<ChargeCarrier, BasicMatrix> _transfer_efficiencies = new EnumMap<ChargeCarrier,BasicMatrix>(ChargeCarrier.class);
59      
60      // bulk - propoerties of the bulk
61      private DopedSilicon _bulk;
62      private double _thickness;  // accessed often, cached here for speed
63      
64      // operating point
65      private double _depletion_voltage;
66      private double _bias_voltage;
67      
68      // Constructors
69      //=============
70      
71      // Default defines everything but electrode configuration
72      public SiSensor(
73              int sensorid,
74              String name,
75              IDetectorElement parent,
76              String support,
77              IIdentifier id
78              )
79      {
80          super(name,parent,support,id);
81          setSensorID(sensorid);
82          setBulk(new DopedSilicon());
83          setDepletionVoltage(SiSensor._DEPLETION_VOLTAGE_DEFAULT);
84          setBiasVoltage(SiSensor._BIAS_VOLTAGE_DEFAULT);
85      }
86      
87      public SiSensor(
88              int sensorid,
89              String name,
90              IDetectorElement parent,
91              String support
92              )
93      {
94          super(name,parent,support);
95          setSensorID(sensorid);
96          setBulk(new DopedSilicon());
97          setDepletionVoltage(SiSensor._DEPLETION_VOLTAGE_DEFAULT);
98          setBiasVoltage(SiSensor._BIAS_VOLTAGE_DEFAULT);
99      }
100     
101     
102     // Accessors
103     //==========
104     
105     // Setters
106     //--------
107     public void setSensorID(int sensorid)
108     {
109         _sensorid = sensorid;
110     }
111     
112     public void setSenseElectrodes(SiSensorElectrodes sense_electrodes)
113     {
114         _sense_electrodes.put(sense_electrodes.getChargeCarrier(),sense_electrodes);
115     }
116     
117     public void setReadoutElectrodes(SiSensorElectrodes readout_electrodes)
118     {
119         _readout_electrodes.put(readout_electrodes.getChargeCarrier(),readout_electrodes);
120     }
121     
122     public void setBiasSurface(ChargeCarrier carrier, Polygon3D bias_surface)
123     {
124         _bias_surfaces.put(carrier,bias_surface);
125     }
126     
127     public void setTransferEfficiencies(ChargeCarrier carrier, BasicMatrix transfer_efficiencies)
128     {
129         _transfer_efficiencies.put(carrier,transfer_efficiencies);
130     }
131     
132     public void setBulk(DopedSilicon bulk)
133     {
134         _bulk = bulk;
135     }
136     
137     public void setDepletionVoltage(double depletion_voltage)
138     {
139         _depletion_voltage = depletion_voltage;
140     }
141     
142     public void setBiasVoltage(double bias_voltage)
143     {
144         _bias_voltage = bias_voltage;
145     }
146     
147     // Getters
148     public int getSensorID()
149     {
150         return _sensorid;
151     }
152     
153     public Collection<SiSensorElectrodes> getSenseElectrodes()
154     {
155         return _sense_electrodes.values();
156     }
157     
158     public SiSensorElectrodes getSenseElectrodes(ChargeCarrier carrier)
159     {
160         return _sense_electrodes.get(carrier);
161     }
162     
163     public Collection<SiSensorElectrodes> getReadoutElectrodes()
164     {
165         return _readout_electrodes.values();
166     }
167     
168     public SiSensorElectrodes getReadoutElectrodes(ChargeCarrier carrier)
169     {
170         return _readout_electrodes.get(carrier);
171     }
172     
173     public Polygon3D getBiasSurface(ChargeCarrier carrier)
174     {
175         return _bias_surfaces.get(carrier);
176     }
177     
178     public BasicMatrix getTransferEfficiencies(ChargeCarrier carrier)
179     {
180         return _transfer_efficiencies.get(carrier);
181     }
182     
183     public DopedSilicon getBulk()
184     {
185         return _bulk;
186     }
187     
188     public double getThickness()
189     {
190         if (_thickness == 0)
191         {
192             
193             
194 //            System.out.println("Hole plane normal: "+_bias_surfaces.get(ChargeCarrier.HOLE).getPlane().getNormal());
195 //            System.out.println("Hole plane direction: "+_bias_surfaces.get(ChargeCarrier.HOLE).getPlane().getDistance());
196 //
197 //            System.out.println("Electron plane normal: "+_bias_surfaces.get(ChargeCarrier.ELECTRON).getPlane().getNormal());
198 //            System.out.println("Electron plane direction: "+_bias_surfaces.get(ChargeCarrier.ELECTRON).getPlane().getDistance());
199             
200             _thickness = Math.abs(GeomOp3D.distanceBetween( _bias_surfaces.get(ChargeCarrier.HOLE).getPlane(), _bias_surfaces.get(ChargeCarrier.ELECTRON).getPlane()));
201             
202 //            System.out.println("Calculated thickness: "+_thickness);
203         }
204         return _thickness;
205     }
206     
207     public double getDepletionVoltage()
208     {
209         return _depletion_voltage;
210     }
211     
212     public double getBiasVoltage()
213     {
214         return _bias_voltage;
215     }
216     
217     public Hep3Vector getBField(Hep3Vector local_position)
218     {
219         
220         IDetectorElement ancestor = this.getParent();
221         while (!(ancestor instanceof DeDetector) && !(ancestor==null))
222         {
223             ancestor = ancestor.getParent();
224         }
225         if (ancestor == null) throw new RuntimeException("SiSensor.getBField CANNOT FIND DETECTOR!!");
226         
227         Hep3Vector global_position = getGeometry().getLocalToGlobal().transformed(local_position);
228         Hep3Vector field_global = ((DeDetector)ancestor).getBField(global_position);
229 //        Hep3Vector field_global = new BasicHep3Vector(0,0,5);
230         
231         return getGeometry().getGlobalToLocal().rotated(field_global);
232         
233     }
234     
235     // Operators
236     //==========
237 //    public void initialize()
238 //    {
239 //        // Cache thickness of bulk
240 //        _thickness = Math.abs(GeomOp3D.distanceBetween( _bias_surfaces.get(ChargeCarrier.HOLE).getPlane(), _bias_surfaces.get(ChargeCarrier.HOLE).getPlane()));
241 //
242 //    }
243     
244     public boolean isACCoupled(ChargeCarrier carrier)
245     {
246         return (this._readout_electrodes.get(carrier) != null);
247     }
248     
249     public boolean isDoubleSided()
250     {
251         boolean double_sided = true;
252         for (ChargeCarrier carrier : ChargeCarrier.values())
253         {
254             double_sided = double_sided && hasElectrodesOnSide(carrier);
255         }
256         return double_sided;
257     }
258     
259     public boolean hasStrips()
260     {
261         boolean has_strips = false;
262         for (SiSensorElectrodes electrodes : getReadoutElectrodes())
263         {
264             has_strips = has_strips || (electrodes instanceof SiStrips);
265         }
266         return has_strips;
267     }
268     
269     public boolean hasPixels()
270     {
271         boolean has_pixels = false;
272         for (SiSensorElectrodes electrodes : getReadoutElectrodes())
273         {
274             has_pixels = has_pixels || (electrodes instanceof SiPixels);
275         }
276         return has_pixels;
277     }
278     
279     public double distanceFromSide(Hep3Vector point, ChargeCarrier carrier)
280     {
281 //        System.out.println("distanceFromSide: "+-GeomOp3D.distanceBetween(new Point3D(point),_bias_surfaces.get(carrier).getPlane()));
282         
283         
284         return -GeomOp3D.distanceBetween(new Point3D(point),_bias_surfaces.get(carrier).getPlane());
285 //        ITransform3D electrode_transform = _sense_electrodes.get(carrier).getParentToLocal().inverse();
286 //        Plane3D electrode_plane = _sense_electrodes.get(carrier).getGeometry().transformed(electrode_transform).getPlane();
287 //
288 //        return GeomOp3D.distanceBetween(new Point3D(point),electrode_plane);
289     }
290     
291     public boolean hasElectrodesOnSide(ChargeCarrier carrier)
292     {
293         if(_sense_electrodes.get(carrier) == null) return false;
294         else return true;
295     }
296     
297     public Hep3Vector electricField(Hep3Vector position)
298     {
299         
300         // See Gorelov
301         double electric_field_magnitude = (_bias_voltage-_depletion_voltage)/getThickness() +
302                 (2.0*_depletion_voltage)/getThickness() * (1.0 - this.distanceFromSide(position,ChargeCarrier.ELECTRON));
303 //        System.out.println("Electric field strength: "+electric_field_magnitude);
304 //        System.out.println("Distance from side: "+this.distanceFromSide(position,ChargeCarrier.ELECTRON));
305 //        System.out.println("Thickness: "+getThickness());
306         
307         Hep3Vector electric_field_direction = _bias_surfaces.get(ChargeCarrier.HOLE).getNormal();
308         
309 //        System.out.println("Electric field direction: "+electric_field_direction);
310         
311         return VecOp.mult(electric_field_magnitude,electric_field_direction);
312         
313         
314 //        Hep3Vector electric_field_direction = null;
315 //        for (ChargeCarrier carrier : ChargeCarrier.values())
316 //        {
317 //            if (hasElectrodesOnSide(carrier))
318 //            {
319 //                ITransform3D electrode_transform = _sense_electrodes.get(carrier).getParentToLocal().inverse();
320 //                Plane3D electrode_plane = _sense_electrodes.get(carrier).getGeometry().transformed(electrode_transform).getPlane();
321 //                electric_field_direction = VecOp.mult(carrier.charge(),electrode_plane.getNormal());
322 //                if (!(electric_field_direction == null)) break;
323 //            }
324 //        }
325 //
326 ////        Hep3Vector electric_field_direction = (this._orientation == Orientation.PSIDE_POSITIVE_Z) ?
327 ////            new BasicHep3Vector(0.0,0.0,1.0) : new BasicHep3Vector(0.0,0.0,-1.0);
328 //
329 //        double electric_field_magnitude = (_bias_voltage-_depletion_voltage)/_thickness +
330 //                (2.0*_depletion_voltage)/_thickness * (1.0 - this.distanceFromSide(position,ChargeCarrier.ELECTRON));
331 //
332 //        return VecOp.mult(electric_field_magnitude,electric_field_direction);
333         
334     }
335     
336     public String toString()
337     {
338         String newline = System.getProperty("line.separator");
339         String output = "SiSensor Object: "+newline+
340                 "   Property 1";
341         return output;
342     }
343     
344     /**
345      * Make an {@link IIdentifier} for a given strip number and side number.
346      *
347      * @param stripNumber The strip number, which should be from 1 to nstrips - 1.
348      * @param sideNumber  The side number, which should be 1 or -1.
349      * @return A 64-bit   A packed id for the strip.
350      */
351     public IIdentifier makeStripId( int stripNumber, int sideNumber )
352     {
353         // Copy the DetectorElement's identifier, which will leave blank fields
354         // for side and strip.
355         IExpandedIdentifier id = new ExpandedIdentifier(getExpandedIdentifier());
356         
357         // Get the helper and dictionary.
358         IIdentifierHelper helper = getIdentifierHelper();
359         IIdentifierDictionary dict = helper.getIdentifierDictionary();
360         
361         // Fill in the side and strip numbers.
362         id.setValue(dict.getFieldIndex("side"), sideNumber);
363         id.setValue(dict.getFieldIndex("strip"), stripNumber);
364         
365         // Pack and return the id.
366         return helper.pack( id );
367     }
368 }