View Javadoc

1   package org.lcsim.recon.tracking.vsegment.digitization;
2   
3   import java.util.*;
4   
5   import org.lcsim.event.EventHeader;
6   import org.lcsim.recon.cat.util.NoSuchParameterException;
7   import org.lcsim.util.Driver;
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.base.DigiTrackerHitComposite;
12  
13  /**
14   * Driver that merges several collections of {@link DigiTrackerHit} objects into one,
15   * combining hits in the same channels.
16   * <p>
17   * Input collections (either <tt>HashMap&lt;Sensor, ArrayList&lt;DigiTrackerHit&gt;&gt;</tt> or
18   * <tt>Collection&lt;DigiTrackerHit&gt;</tt>) are fetched from the event usung name supplied
19   * through calls to <tt>set("ADD_INPUT_COLLECTION", name)</tt>, and output collection
20   * (type <tt>HashMap&lt;Sensor, ArrayList&lt;DigiTrackerHit&gt;&gt;</tt>) is attached
21   * to the event with the name set by a call to <tt>set("OUTPUT_MAP_NAME", name)</tt>.
22   * <p>
23   * Whenever input collections contain hits in the same channels, new <tt>DigiTrackerHit</tt>
24   * objects of type {@link DigiTrackerHitComposite} are created and stored in the output
25   * map. These new objects reference all the original hits as their constituents.
26   * <p>
27   * {@link #merge} methods can also be called directly by other classes.
28   *
29   * @author D. Onoprienko
30   * @version $Id: MergeDriver.java,v 1.1 2008/12/06 21:53:43 onoprien Exp $
31   */
32  public class MergeDriver extends Driver {
33    
34  // -- Constructors :  ----------------------------------------------------------
35    
36    /** Default constructor. */
37    public MergeDriver() {}
38    
39  // -- Setters :  ---------------------------------------------------------------
40  
41    /**
42     * Set parameters. 
43     * The following parameters can be set with this method:
44     * <dl>
45     * <dt>"ADD_INPUT_COLLECTION"</dt> <dd>Name of input collection of digitized hits
46     *                 (type <tt>HashMap<Sensor, ArrayList<DigiTrackerHit>></tt>).<br>
47     *                 No default.</dd>
48     * <dt>"OUTPUT_MAP_NAME"</dt> <dd>Name of output collection of clusters
49     *                 (type <tt>HashMap<Sensor, ArrayList<DigiTrackerHit>></tt>).<br>
50     *                 No default.</dd></dl>
51     * 
52     * @param name   Name of parameter to be set. Case is ignored.
53     * @param value  Value to be assigned to the parameter.
54     * @throws NoSuchParameterException Thrown if the supplied parameter name is unknown.
55     *         Subclasses may catch this exception after a call to <tt>super.set()</tt>
56     *         and set their own parameters.
57     */
58    public void set(String name, Object value) {
59      try {
60        if (name.equalsIgnoreCase("ADD_INPUT_COLLECTION")) {
61          _inMapNames.add((String)value);
62        } else if (name.equalsIgnoreCase("OUTPUT_MAP_NAME")) {
63          _outMapName = (String)value;
64        } else {
65          throw new NoSuchParameterException(name, this.getClass());
66        }
67      } catch (ClassCastException x) {
68        throw new IllegalArgumentException("Value of incompatible type", x);
69      }
70   }
71    
72  // -- Event processing :  ------------------------------------------------------
73    
74    /** Called by framework to process event. */
75    public void process(EventHeader event) {
76      
77      if (_inMapNames == null) throw new RuntimeException("No input collection names provided");
78      if (_outMapName == null) throw new RuntimeException("No output collection name provided");
79      
80      ArrayList<HashMap<Sensor, ArrayList<DigiTrackerHit>>> inMaps = 
81              new ArrayList<HashMap<Sensor, ArrayList<DigiTrackerHit>>>(_inMapNames.size());
82      for (String name : _inMapNames) {
83        inMaps.add((HashMap<Sensor, ArrayList<DigiTrackerHit>>) event.get(name));
84      }
85      
86      HashMap<Sensor, ArrayList<DigiTrackerHit>> outMap = merge(inMaps);
87      event.put(_outMapName, outMap);
88    }
89    
90  // -- Merging :  ---------------------------------------------------------------
91    
92    /**
93     * Returns the result of merging <tt>DigiTrackerHits</tt> from several maps.
94     */
95    public HashMap<Sensor, ArrayList<DigiTrackerHit>> merge(Collection<HashMap<Sensor, ArrayList<DigiTrackerHit>>> hitMaps) {
96      HashMap<Sensor, ArrayList<DigiTrackerHit>> outMap = new HashMap<Sensor, ArrayList<DigiTrackerHit>>();
97      for (HashMap<Sensor, ArrayList<DigiTrackerHit>> inMap : hitMaps) {
98        for (Sensor sensor : inMap.keySet()) {
99          ArrayList<DigiTrackerHit> inList = inMap.get(sensor);
100         ArrayList<DigiTrackerHit> outList = outMap.get(sensor);
101         if (outList == null) {
102           outList = new ArrayList<DigiTrackerHit>(inList.size());
103           outMap.put(sensor, outList);
104         }
105         outList.addAll(inList);
106       }
107     }
108     for (Sensor sensor : outMap.keySet()) {
109       outMap.put(sensor, merge(outMap.get(sensor)));
110     }
111     return outMap;
112   }
113   
114   /**
115    * Returns a list of hits produced by merging hits in the list supplied as an argument.
116    * The output list is sorted by channel ID.
117    */
118   public ArrayList<DigiTrackerHit> merge(ArrayList<DigiTrackerHit> hitList) {
119     Collections.sort(hitList);
120     ArrayList<DigiTrackerHit> outList = new ArrayList<DigiTrackerHit>(hitList.size());
121     int channel = -1;
122     ArrayList<DigiTrackerHit> buffer = new ArrayList<DigiTrackerHit>();
123     for (DigiTrackerHit hit : hitList) {
124       int newChannel = hit.getChannel();
125       if (buffer.isEmpty()) {
126         buffer.add(hit);
127         channel = newChannel;
128       } else if (channel == newChannel) {
129         buffer.add(hit);
130       } else {
131         if (buffer.size() == 1) {
132           outList.add(buffer.get(0));
133         } else {
134           outList.add(new DigiTrackerHitComposite(buffer));
135         }
136         buffer.clear();
137         buffer.add(hit);
138         channel = newChannel;
139       }
140     }
141     if (! buffer.isEmpty()) {
142       if (buffer.size() == 1) {
143         outList.add(buffer.get(0));
144       } else {
145         outList.add(new DigiTrackerHitComposite(buffer));
146       }
147     }
148     outList.trimToSize();
149     return outList;
150   }
151 
152 // -- Private parts :  ---------------------------------------------------------
153 
154   ArrayList<String> _inMapNames;
155   String _outMapName;
156 }