View Javadoc

1   package org.lcsim.recon.tracking.vsegment.mctruth;
2   
3   import java.util.*;
4   
5   import org.lcsim.event.EventHeader;
6   import org.lcsim.event.MCParticle;
7   import org.lcsim.event.SimTrackerHit;
8   
9   import org.lcsim.recon.tracking.vsegment.geom.Sensor;
10  import org.lcsim.recon.tracking.vsegment.hit.DigiTrackerHit;
11  import org.lcsim.recon.tracking.vsegment.hit.TrackerCluster;
12  import org.lcsim.recon.tracking.vsegment.hit.TrackerHit;
13  import org.lcsim.recon.tracking.vsegment.hitmaking.OldTrackerHit;
14  
15  /**
16   * An object of this class provides convenient access to Monte Carlo truth information.
17   * In order for this object to be created, an instance of {@link MCTruthDriver} should
18   * be added to the processing chain (usually as the first driver).
19   *
20   * @author D. Onoprienko
21   * @version $Id: MCTruth.java,v 1.1 2008/12/06 21:53:44 onoprien Exp $
22   */
23  public class MCTruth {
24    
25  // -- Constructors :  ----------------------------------------------------------
26    
27    MCTruth(MCTruthDriver mcTruthDriver, EventHeader event) {
28      _mcDriver = mcTruthDriver;
29      _event = event;
30      _digiToSimGroup = new HashMap<DigiTrackerHit, SimGroup>();
31      _missedSimGroups = new ArrayList<SimGroup>();
32    }
33    
34  // -- Getting SimTrackerHits from which the object was produced :  -------------
35    
36    /**
37     * Returns a list of <tt>SimGroup</tt> objects containing <tt>SimTrackerHits</tt>
38     * that contributed to the given <tt>DigiTrackerHit</tt>. 
39     */
40    public List<SimGroup> getSimGroups(DigiTrackerHit hit) {
41      ArrayList<SimGroup> out = new ArrayList<SimGroup>(1);
42      List<DigiTrackerHit> elHits= hit.getElementalHits();
43      for (DigiTrackerHit elHit : elHits) {
44        SimGroup group = _digiToSimGroup.get(elHit);
45        if (group != null) out.add(group);
46      }
47      return out;
48    }
49    
50    /**
51     * Returns a list of <tt>SimGroup</tt> objects containing <tt>SimTrackerHits</tt>
52     * that contributed to the given <tt>TrackerCluster</tt>. 
53     */
54    public List<SimGroup> getSimGroups(TrackerCluster cluster) {
55      List<SimGroup> out = null;
56      for (DigiTrackerHit hit : cluster.getDigiHits()) {
57        if (out == null) {
58          out = getSimGroups(hit);
59        } else {
60          out.addAll(getSimGroups(hit));
61        }
62      }
63      return out;
64    }
65    
66    /**
67     * Returns a list of <tt>SimGroup</tt> objects containing <tt>SimTrackerHits</tt>
68     * that contributed to the given <tt>TrackerHit</tt>. 
69     */
70    public List<SimGroup> getSimGroups(TrackerHit hit) {
71      return getSimGroups(hit.getCluster());
72    }
73    
74    /**
75     * Returns a list of <tt>SimGroup</tt> objects containing <tt>SimTrackerHits</tt>
76     * that contributed to the given hit. 
77     */
78    public List<SimGroup> getSimGroups(org.lcsim.event.TrackerHit oldHit) {
79      if (oldHit instanceof OldTrackerHit) {
80        List<SimGroup> out = null;
81        for (TrackerCluster cluster : ((OldTrackerHit)oldHit).getClusters()) {
82          if (out == null) {
83            out = getSimGroups(cluster);
84          } else {
85            out.addAll(getSimGroups(cluster));
86          }
87        }
88        return out;
89      } else {
90        throw new IllegalArgumentException();
91      }
92    }
93    
94    /**
95     * Returns a collection of all <tt>SimGroup</tt> objects containing <tt>SimTrackerHits</tt>
96     * that contributed to any <tt>DigiTrackerHits</tt>. 
97     */
98    public Collection<SimGroup> getSimGroups() {
99      return _digiToSimGroup.values();
100   }
101   
102   /**
103    * Returns a collection of all <tt>SimGroup</tt> objects containing <tt>SimTrackerHits</tt>
104    * that did not contribute to any <tt>DigiTrackerHits</tt>. 
105    */
106   public List<SimGroup> getMissedSimGroups() {
107     return _missedSimGroups;
108   }
109   
110 // -- Getting MCParticles :  ---------------------------------------------------
111   
112   /** Returns <tt>MCParticle</tt> that produced <tt>SimTrackerHits</tt> in the given <tt>SimGroup</tt>. */
113   public MCParticle getMCParticle(SimGroup simGroup) {
114     return simGroup.getMCParticle();
115   }
116   
117   /** Returns a list of <tt>MCParticles</tt> that contributed to the given <tt>DigiTrackerHit</tt>. */
118   public List<MCParticle> getMCParticles(DigiTrackerHit hit) {
119     ArrayList<MCParticle> out = new ArrayList<MCParticle>();
120     for (DigiTrackerHit elementalHit : hit.getElementalHits()) {
121       MCParticle mc = elementalHit.getMCParticle();
122       if ((mc != null) && (! out.contains(mc))) out.add(mc);
123     }
124     out.trimToSize();
125     return out;
126   }
127   
128   /** Returns a list of <tt>MCParticles</tt> that contributed to the given <tt>TrackerCluster</tt>. */
129   public List<MCParticle> getMCParticles(TrackerCluster cluster) {
130     List<MCParticle> out = null;
131     for (DigiTrackerHit hit : cluster.getDigiHits()) {
132       if (out == null) {
133         out = getMCParticles(hit);
134       } else {
135         for (MCParticle mc : getMCParticles(hit)) {
136           if (! out.contains(mc)) out.add(mc);
137         }
138       }
139     }
140     return out;
141   }
142   
143   /** Returns a list of <tt>MCParticles</tt> that contributed to the given <tt>TrackerHit</tt>. */
144   public List<MCParticle> getMCParticles(TrackerHit hit) {
145     return getMCParticles(hit.getCluster());
146   }
147   
148   /** Returns a list of <tt>MCParticles</tt> that contributed to the given hit. */
149   public List<MCParticle> getMCParticles(org.lcsim.event.TrackerHit oldHit) {
150     if (oldHit instanceof OldTrackerHit) {
151       List<MCParticle> out = null;
152       for (TrackerCluster cluster : ((OldTrackerHit)oldHit).getClusters()) {
153         if (out == null) {
154           out = getMCParticles(cluster);
155         } else {
156           for (MCParticle mc : getMCParticles(cluster)) {
157             if (! out.contains(mc)) out.add(mc);
158           }
159         }
160       }
161       return out;
162     } else {
163       throw new IllegalArgumentException();
164     }
165   }
166   
167 // -- Looking up tracking objects by MCParticle :  -----------------------------
168 
169   /**
170    * Returns a list of <tt>SimGroups</tt> associated with the given MCParticle, sorted by time.
171    * The list returned by this method belongs to this <tt>MCTruth</tt> object,
172    * clients should not modify it.
173    */
174   public List<SimGroup> getSimGroups(MCParticle mcParticle) {
175     if (_mcToSimGroupList == null) {
176       _mcToSimGroupList = new HashMap<MCParticle, ArrayList<SimGroup>>();
177       for (SimGroup group : _digiToSimGroup.values()) {
178         MCParticle mc = group.getMCParticle();
179         ArrayList<SimGroup> groupList = _mcToSimGroupList.get(mc);
180         if (groupList == null) {
181           groupList = new ArrayList<SimGroup>();
182           _mcToSimGroupList.put(mc, groupList);
183         }
184         groupList.add(group);
185       }
186       for (SimGroup group : _missedSimGroups) {
187         MCParticle mc = group.getMCParticle();
188         ArrayList<SimGroup> groupList = _mcToSimGroupList.get(mc);
189         if (groupList == null) {
190           groupList = new ArrayList<SimGroup>();
191           _mcToSimGroupList.put(mc, groupList);
192         }
193         groupList.add(group);        
194       }
195       for (ArrayList<SimGroup> groupList : _mcToSimGroupList.values()) {
196         Collections.sort(groupList, _compSimGroup);
197         groupList.trimToSize();
198       }
199     }
200     List<SimGroup> out = _mcToSimGroupList.get(mcParticle);
201     if (out == null) out = Collections.emptyList();
202     return out;
203   }
204   
205   /**
206    * Returns a list of <tt>TrackerClusters</tt> associated with the given MCParticle, sorted by time.
207    * The list returned by this method belongs to this <tt>MCTruth</tt> object,
208    * clients should not modify it.
209    */
210   public List<TrackerCluster> getTrackerClusters(MCParticle mcParticle) {
211     if (_mcToTrackerCluster == null) {
212       _mcToTrackerCluster = new HashMap<MCParticle, ArrayList<TrackerCluster>>();
213       for (List<TrackerCluster> clusterList : _trackingClusters.values()) {
214         for (TrackerCluster cluster : clusterList) {
215           List<MCParticle> mcList = getMCParticles(cluster);
216           for (MCParticle mc : mcList) {
217             ArrayList<TrackerCluster> clusters = _mcToTrackerCluster.get(mc);
218             if (clusters == null) {
219               clusters = new ArrayList<TrackerCluster>();
220               _mcToTrackerCluster.put(mc, clusters);
221             }
222             clusters.add(cluster);
223           }
224         }
225       }
226       for (ArrayList<TrackerCluster> clusters : _trackingClusters.values()) {
227         Collections.sort(clusters, _compTrackerCluster);
228         clusters.trimToSize();        
229       }
230     }
231     List<TrackerCluster> out = _mcToTrackerCluster.get(mcParticle);
232     if (out == null) out = Collections.emptyList();
233     return out;
234   }
235   
236 // -- Stereo :  ----------------------------------------------------------------
237   
238   /**
239    * Returns <tt>true</tt> if the hit supplied as an argument is a cross between hits
240    * in stereo layer, and no MCParticle contributed to both of its parent clusters.
241    */
242   public boolean isGhost(OldTrackerHit hit) {
243     if (! hit.isStereo()) return false;
244     List<TrackerCluster> clusters = hit.getClusters();
245     List<MCParticle> mcList1 = getMCParticles(clusters.get(0));
246     List<MCParticle> mcList2 = getMCParticles(clusters.get(1));
247     for (MCParticle mc : mcList1) {
248       if (mcList2.contains(mc)) return false;
249     }
250     return true;
251   }
252 
253 // -- Modifiers :  -------------------------------------------------------------
254   
255   /**
256    * This method is called by <tt>DigitizationDriver</tt> to create a new <tt>SimGroup</tt>
257    * and store it in this <tt>MCTruth</tt> object.
258    */
259   public void addSimGroup(Collection<SimTrackerHit> simTrackerHits, Collection<DigiTrackerHit> digiTrackerHits) {
260     SimGroup simGroup = new SimGroup(simTrackerHits, digiTrackerHits);
261     if (digiTrackerHits.isEmpty()) {
262       _missedSimGroups.add(simGroup);
263     } else {
264       for (DigiTrackerHit dHit : digiTrackerHits) {
265         _digiToSimGroup.put(dHit, simGroup);
266       }
267     }
268   }
269   
270   /** 
271    * Called by <tt>ClusteringDriver</tt> to store a reference to the <tt>TrackerCluster</tt> map.
272    */
273   public void setTrackerClusters(HashMap<Sensor, ArrayList<TrackerCluster>> clusters) {
274     _trackingClusters = clusters;
275   }
276   
277 // -- Private parts :  ---------------------------------------------------------
278   
279   private MCTruthDriver _mcDriver;
280   private EventHeader _event;
281   private HashMap<Sensor, ArrayList<TrackerCluster>> _trackingClusters;
282 
283   private HashMap<DigiTrackerHit, SimGroup> _digiToSimGroup;
284   private ArrayList<SimGroup> _missedSimGroups;
285   
286   private HashMap<MCParticle, ArrayList<SimGroup>> _mcToSimGroupList;
287   private HashMap<MCParticle, ArrayList<TrackerCluster>> _mcToTrackerCluster;
288   
289   private static Comparator<SimGroup> _compSimGroup = new Comparator<SimGroup>() {
290     public int compare(SimGroup s1, SimGroup s2) {
291       return (int)Math.signum(s1.getTime() - s2.getTime());
292     }
293   };
294   private static Comparator<TrackerCluster> _compTrackerCluster = new Comparator<TrackerCluster>() {
295     public int compare(TrackerCluster s1, TrackerCluster s2) {
296       return (int)Math.signum(s1.getTime() - s2.getTime());
297     }
298   };
299   
300 }