View Javadoc

1   package org.lcsim.event.base;
2   
3   import hep.physics.vec.BasicHep3Vector;
4   import hep.physics.vec.Hep3Vector;
5   
6   import org.lcsim.detector.DetectorElement;
7   import org.lcsim.detector.DetectorElementStore;
8   import org.lcsim.detector.DetectorIdentifierHelper;
9   import org.lcsim.detector.IDetectorElement;
10  import org.lcsim.detector.IDetectorElementContainer;
11  import org.lcsim.detector.identifier.IExpandedIdentifier;
12  import org.lcsim.detector.identifier.IIdentifier;
13  import org.lcsim.detector.identifier.IIdentifierHelper;
14  import org.lcsim.event.EventHeader.LCMetaData;
15  import org.lcsim.event.Hit;
16  import org.lcsim.geometry.IDDecoder;
17  import org.lcsim.geometry.Subdetector;
18  import org.lcsim.geometry.subdetector.BarrelEndcapFlag;
19  
20  /**
21   * This is a base class for hit-like objects in a detector.
22   * 
23   * @author Jeremy McCormick <jeremym@slac.stanford.edu>
24   */
25  public abstract class BaseHit implements Hit {
26      
27      protected LCMetaData metaData;
28      protected IExpandedIdentifier expandedID;
29      protected IIdentifier packedID;
30      protected IDetectorElement detectorElement;
31      protected Hep3Vector positionVec;
32  
33      /**
34       * Get the metadata associated with this hit.     
35       * @return The hit's metadata.
36       */
37      public LCMetaData getMetaData() {
38          return metaData;
39      }
40  
41      /**
42       * Set the metadata associated with this hit.
43       */
44      public void setMetaData(LCMetaData meta) {
45                  
46          this.metaData = meta;               
47      }
48      
49      /**
50       * Get the subdetector of this hit.     
51       * @return The Subdetector of this hit.
52       */
53      public Subdetector getSubdetector() {
54          return getIDDecoder().getSubdetector();
55      }
56  
57      /**
58       * Get the {@see org.lcsim.detector.IDetectorElement} associated with this hit.     
59       * @return The IDetectorElement for this hit.
60       */
61      public IDetectorElement getDetectorElement() {
62          if (detectorElement == null) {
63              // Attempt to lookup the geometry using this exact ID.
64              detectorElement = findDetectorElement(getIdentifier());
65              if (detectorElement == null) {
66                  // Presumably if the ID lookup fails, this means it has non-geometric fields,
67                  // so use the global position instead.
68                  if (getPositionVec() != null) {
69                      detectorElement = findDetectorElement(getPositionVec());
70                  }                
71                  // Just leave it as null!
72              }
73          }
74          return detectorElement;
75      }
76      
77      /**
78       * Set the @see org.lcsim.detector.IDetectorElement of this hit. By default, this will not override an
79       * existing value.
80       */
81      public void setDetectorElement(IDetectorElement de) {
82          this.detectorElement = de;        
83      }
84  
85      /**
86       * Get the {@see org.lcsim.detector.identifier.IExpandedIdentifier} of this hit.     
87       * @return The expanded identifier of this hit.
88       */
89      public IExpandedIdentifier getExpandedIdentifier() {
90          if (expandedID == null) {
91              expandedID = getIdentifierHelper().unpack(getIdentifier());
92          }
93          return expandedID;
94      }
95  
96      /**
97       * Get the identifier of this hit.     
98       * @return The identifier of this hit.
99       */
100     public IIdentifier getIdentifier() {
101         return packedID;
102     }
103 
104     /**
105      * Get the identifier helper of this hit.     
106      * @return The hit's identifier helper.
107      */
108     public IIdentifierHelper getIdentifierHelper() {
109         return getSubdetector().getDetectorElement().getIdentifierHelper();
110     }
111 
112     /**
113      * Get the detector identifier helper of this hit.   
114      * @return The hit's detector identifier helper.
115      */
116     public DetectorIdentifierHelper getDetectorIdentifierHelper() {
117         return (DetectorIdentifierHelper)getIdentifierHelper();
118     }
119 
120     /**
121      * Get the {@see org.lcsim.geometryIDDecoder} of this hit.     
122      * @return The hit's id decoder.
123      */
124     public IDDecoder getIDDecoder() {
125         return metaData.getIDDecoder();
126     }
127 
128     /**
129      * Get the layer number of this hit.    
130      * @return The layer number of this hit.
131      */
132     public int getLayerNumber() {
133         return getIdentifierHelper().getValue(getIdentifier(), "layer");
134     }
135 
136     /**
137      * Get the barrel flag of this hit.    
138      * @return The barrel flag of this hit.
139      */
140     public BarrelEndcapFlag getBarrelEndcapFlag() {
141         return BarrelEndcapFlag.createBarrelEndcapFlag(getIdentifierHelper().getValue(getIdentifier(), "barrel"));
142     }
143 
144     /**
145      * Get the system id of this hit.
146      * @return The system id of this hit.
147      */
148     public int getSystemId() {
149         return getIdentifierHelper().getValue(getIdentifier(), "system");
150     }
151 
152     /**
153      * Get a field value from the hit's identifier.     
154      * @return The field value from the hit's identifier.
155      */
156     public int getIdentifierFieldValue(String field) {
157         return getIdentifierHelper().getValue(getIdentifier(), field);
158     }
159                   
160     /**    
161      * Get the position of the hit.  This may be different than the position of the hit's DetectorElement.
162      * @return The position of this hit as a double array of size 3.
163      */
164     public double[] getPosition() {
165         if (positionVec == null) {
166             calculatePosition();
167         }
168         return positionVec.v();
169     }
170     
171     /**
172      * Get the position of this hit in mm as a {@see hep.physics.vec.Hep3Vector}.
173      * @return The position vector of the hit in mm.
174      */
175     public Hep3Vector getPositionVec() { 
176         return positionVec;
177     }       
178     
179     /**
180      * Calculate the position of the hit, depending on what information is available on the object.
181      */
182     protected void calculatePosition() {
183         // Is the position not set already?
184         if (positionVec == null) {
185             
186             // Is the detector object not set yet?
187             if (detectorElement == null) {
188                 // Try to find a detector object to link to this hit.
189                 detectorElement = findDetectorElement(getIdentifier());
190             }
191             
192             // Does the hit ID match the DetectorElement exactly?
193             if (detectorElement != null && detectorElement.getIdentifier().equals(getIdentifier())) {
194                 // Set the position from the DetectorElement.
195                 this.positionVec = detectorElement.getGeometry().getPosition();                
196             } else {
197                 // This is what should happen for IDs with virtual segmentation values.
198                 // The IDDecoder needs to be used here if it is set on the hit.
199                 if (this.metaData != null) {
200                     IDDecoder decoder = this.getIDDecoder();
201                     if (decoder != null) {
202                         decoder.setID(this.getIdentifier().getValue());
203                         this.positionVec = new BasicHep3Vector(decoder.getPosition());
204                     }
205                 }
206             }
207         }
208     }
209             
210     /**
211      * Find a DetectorElement by its identifier.
212      * @param id The identifier.
213      * @return The DetectorElement matching the identifier.
214      */
215     protected IDetectorElement findDetectorElement(IIdentifier id) {
216         IDetectorElement mommy = null;
217         if (this.metaData != null) {
218             // Use subdetector's volume as top.
219             mommy = this.getIDDecoder().getSubdetector().getDetectorElement();
220         } 
221         if (mommy == null) {
222             // Use the world volume as top.
223             mommy = ((DetectorElement) DetectorElementStore.getInstance().get(0)).getTop();
224         }       
225         
226         // Find DetectorElements with exactly matching ID.
227         IDetectorElementContainer detectorElements = mommy.findDetectorElement(id);
228         
229         // FIXME: Beware! The container itself can be null, which should be fixed (detector-framework).
230         if (detectorElements != null && detectorElements.size() == 1) {
231             return detectorElements.get(0); 
232         } else {
233             return null;
234         }
235     }
236     
237     /**
238      * Find a DetectorElement by its global Cartesian position.
239      * @param position The position.
240      * @return The DetectorElement at the position.
241      */
242     protected IDetectorElement findDetectorElement(Hep3Vector position) {                                                                                     
243         IDetectorElement mommy = null;                                                                                                                      
244         if (this.metaData != null) {                                                                                                                        
245             // Use subdetector's volume as top.                                                                                                             
246             mommy = this.getIDDecoder().getSubdetector().getDetectorElement();                                                                              
247         }                                                                                                                                                   
248         if (mommy == null) {                                                                                                                                
249             // Use the world volume.                                                                                                                        
250             mommy = ((DetectorElement) DetectorElementStore.getInstance().get(0)).getTop().findDetectorElement(getPositionVec());                           
251         }                                                                                                                                                   
252         return mommy.findDetectorElement(this.positionVec);                                                                                                 
253     }
254 }