1 package org.lcsim.recon.tracking.trffit; 2 import org.lcsim.recon.tracking.trfbase.ETrack; 3 import org.lcsim.recon.tracking.trfbase.Hit; 4 import org.lcsim.recon.tracking.trfbase.Propagator; 5 6 import org.lcsim.recon.tracking.trfbase.Surface; 7 import org.lcsim.recon.tracking.trfbase.PropStat; 8 import org.lcsim.recon.tracking.trfbase.PropDir; 9 10 import java.util.*; 11 /** 12 * This class describes a track as an ordered list of hits plus 13 * an ETrack (fitted vector and error matrix at a surface) and 14 * the fit chi-square. 15 *<p> 16 * Hits are ordered as they were fit. 17 *<p> 18 * The access to the list of hits is minimal. Users are expected to 19 * construct a new object to do more than update the fit or add a 20 * hit to the end of the list. 21 *<p> 22 * The method is_fit returns true if the track has been fit with all its hits. 23 * This state is set by calling set_fit and is unset when hits are added. 24 * No hits are required to be on the track (so one can store a fit without 25 * any hits). 26 * 27 *@author Norman A. Graf 28 *@version 1.0 29 * 30 */ 31 public class HTrack 32 { 33 // Number of hits used in the current fit. 34 // -1 for a track which has never been fit 35 private int _nfit; 36 37 38 // list of hits 39 protected List _hits; 40 41 // fitted track (or starting track) 42 protected ETrack _tre; 43 44 // fit chi-square 45 protected double _chisq; 46 47 48 // 49 50 /** 51 * Construct an instance that contains no hits and whose fit is invalid. 52 * 53 */ 54 public HTrack() 55 { 56 _tre = new ETrack(); 57 _chisq = 0.0; 58 _nfit = -1; 59 _hits = new ArrayList(); 60 } 61 62 // 63 64 /** 65 *Construct and instance from a track and its error. 66 * There are no hits on the track. 67 * 68 * @param tre The ETrack from which to construct this instance. 69 */ 70 public HTrack( ETrack tre) 71 { 72 _tre = new ETrack(tre); 73 _chisq = 0.0; 74 _nfit = 0; 75 _hits = new ArrayList(); 76 } 77 78 // 79 80 /** 81 *Construct an instance which replicates its argument (Copy Constructor). 82 * 83 * @param ht The HTrack to replicate. 84 */ 85 public HTrack( HTrack ht) 86 { 87 _tre = new ETrack(ht._tre); 88 _chisq = ht._chisq; 89 _nfit = ht._nfit; 90 _hits = new ArrayList(ht._hits); 91 } 92 93 94 // 95 96 /** 97 *Add a hit to the back of the list. 98 * 99 * @param hit The Hit to add to this track. 100 */ 101 public void addHit( Hit hit) 102 {_hits.add(hit); 103 } 104 105 // 106 107 /** 108 *Drop the last hit on the list. This does not affect the fit status. 109 * 110 */ 111 public void dropHit() 112 { 113 _hits.remove(_hits.size()-1); // is there no lastElement in List? 114 } 115 116 // 117 118 /** 119 *Drop all hits. This does not affect the fit status. 120 * 121 */ 122 public void dropHits() 123 { 124 _hits.clear(); 125 } 126 127 // 128 129 130 /** 131 *Set the fit parameters for the current list of hits. 132 *Be sure to add all relevant hits before invocation. 133 * It is assumed the track has been fit with all of its hits. 134 * The track and chi-square are assigned the specified value and 135 * the number of fitted hits is set to the current number of hits. 136 * 137 * @param tre The ETrack which represents the fit parameters and errors. 138 * @param chisq The chi-square of the fit. 139 */ 140 public void setFit( ETrack tre, double chisq) 141 { 142 _tre = new ETrack(tre); 143 _chisq = chisq; 144 _nfit = _hits.size(); 145 } 146 147 // 148 149 150 /** 151 * Unset the fit. 152 * The number of hits is set to 0 and the chi-square is set to zero. 153 * The track is not modified (the last fit becomes the starting track). 154 * 155 */ 156 public void unsetFit() 157 { 158 _nfit = -1; 159 _chisq = 0.0; 160 } 161 162 // 163 164 /** 165 *Unset the fit and reset the starting track. 166 * The fit is unset and the track is set to the specified value. 167 * 168 * @param tre The ETrack which represents the track parameters and errors. 169 */ 170 public void unsetFit( ETrack tre) 171 { 172 unsetFit(); 173 _tre = new ETrack(tre); 174 } 175 176 // 177 178 /** 179 *Return the list of hits. 180 * 181 * @return The list of hits on this track. 182 */ 183 public List hits() 184 { 185 return new ArrayList(_hits); 186 } 187 188 // 189 190 /** 191 *Return a copy of the fit track parameters and errors. 192 * 193 * @return The ETrack which represents the track parameters and errors. 194 */ 195 public ETrack newTrack() 196 { 197 return new ETrack(_tre); 198 } 199 200 // 201 202 /** 203 * Fetch a handle to the fit track parameters and errors. 204 * @return The ETrack which represents the track parameters and errors. 205 */ 206 public ETrack track() 207 { 208 return _tre; 209 } 210 211 // 212 213 /** 214 *Return the chi-square of the track fit. 215 * 216 * @return The chi-square of the track fit. 217 */ 218 public double chisquared() 219 { return _chisq; 220 } 221 222 // 223 224 /** 225 *Return the number of measurements on this track. 226 *This is the number of hits times the dimension of the hit measurement. 227 * 228 * @return The number of measurements on this track. 229 */ 230 public int numberOfMeasurements() 231 { 232 int nmeas = 0; 233 for (Iterator it = _hits.iterator(); it.hasNext(); ) 234 { 235 nmeas+= ((Hit)it.next()).size(); 236 } 237 return nmeas; 238 } 239 240 // 241 242 /** 243 *Return the MC track information for hits on this track. 244 * 245 * @return The TrackMcHitInfo object encapsulating the MC track information for hits on this track. 246 */ 247 public TrackMcHitInfo mcInfo() 248 { 249 List idlist = new ArrayList(); 250 Map idmap = new HashMap(); 251 int nhits = _hits.size(); 252 //Loop over the hits and fill the mcids list with all the McIds 253 List mcids = new ArrayList(); 254 // for (Iterator it = _hits.iterator(); it.hasNext(); ) 255 // { 256 // System.out.println( ((Hit) it.next()).mcIds().size() ); 257 // // mcids.addAll( ((Hit) it.next()).get_mc_ids() ); 258 // } 259 //Iterate over the list and fill the frequency map idmap 260 for (Iterator it = mcids.iterator(); it.hasNext(); ) 261 { 262 Integer freq = (Integer) it.next(); 263 idmap.put( freq, (freq==null ? new Integer(1) : new Integer(freq.intValue()+1)) ); 264 } 265 // Return a TrackMcHitInfo object 266 return new TrackMcHitInfo(nhits, idmap); 267 } 268 269 // 270 271 /** 272 *Return the fit status: true if track has one or more hits 273 * and has been fit with all of its hits. 274 * 275 * @return true if the track contains a valid fit. 276 */ 277 public boolean isFit() 278 { 279 return _tre.isValid() && ( _nfit == _hits.size() ); 280 } 281 282 // 283 284 285 /** 286 *Propagate the fit track. 287 * Note that this does not change the fit status because the propagation 288 * should be reversible. 289 * 290 * @param prop The Propagator to use for propagation. 291 * @param srf The Surface to propagate to. 292 * @return The propagation status. 293 */ 294 public PropStat propagate( Propagator prop, Surface srf) 295 { 296 return prop.errProp(_tre, srf); 297 } 298 299 // 300 301 302 /** 303 *Propagate the fit track in a specified direction. 304 * Note that this does not change the fit status because the propagation 305 * should be reversible. 306 * 307 * @param prop The Propagator to use for propagation. 308 * @param srf The Surface to propagate to. 309 * @param dir The direction in which to propagate. 310 * @return The propagation status. 311 */ 312 public PropStat propagate( Propagator prop, Surface srf, PropDir dir) 313 { 314 return prop.errDirProp(_tre,srf,dir); 315 } 316 317 318 /** 319 *output stream 320 * 321 * @return The String representation of this class. 322 */ 323 public String toString() 324 { 325 StringBuffer sb = new StringBuffer(getClass().getName()+" is "); 326 if( ! isFit()) sb.append("not "); 327 sb.append("fit: \n" + _tre +"\n"); 328 sb.append("Chi-square: "+_chisq+"\n"); 329 sb.append("Track has "+_hits.size()+" hit"); 330 if(_hits.size() != 1) sb.append("s"); 331 if (_hits.size() > 0 ) 332 { 333 sb.append(":\n"); 334 for (Iterator it = _hits.iterator(); it.hasNext(); ) 335 { 336 sb.append( ((Hit) it.next()+"\n") ); 337 } 338 } 339 return sb.toString(); 340 } 341 342 343 /** 344 *Test equality of this object against another HTrack. 345 * 346 * @param ht The HTrack against which to compare. 347 * @return true if the two tracks are equal. 348 */ 349 public boolean equals( HTrack ht) 350 { 351 if( ! hits().equals(ht.hits()) ) return false; 352 if( ! newTrack().equals(ht.newTrack()) ) return false; 353 if( chisquared() != ht.chisquared() ) return false; 354 if( isFit() != ht.isFit() ) return false; 355 return true; 356 } 357 358 359 /** 360 * Test inequality of this object against another HTrack. 361 * 362 * @param ht The HTrack against which to compare. 363 * @return true if the two tracks are equal. 364 */ 365 public boolean notEquals( HTrack ht) 366 { 367 return ! equals(ht); 368 } 369 } 370 371