1 package org.lcsim.recon.tracking.trfzp; 2 3 import java.util.Map; 4 import java.util.HashMap; 5 import java.util.TreeMap; 6 import java.util.SortedMap; 7 8 import java.util.List; 9 import java.util.LinkedList; 10 import java.util.ArrayList; 11 import java.util.Iterator; 12 import java.util.ListIterator; 13 14 import org.lcsim.recon.tracking.trfutil.Assert; 15 import org.lcsim.recon.tracking.trfutil.TRFMath; 16 17 import org.lcsim.recon.tracking.trfbase.Cluster; 18 import org.lcsim.recon.tracking.trfbase.Hit; 19 import org.lcsim.recon.tracking.trfbase.Surface; 20 import org.lcsim.recon.tracking.trfbase.ETrack; 21 22 import org.lcsim.recon.tracking.trflayer.ClusterFindManager; 23 24 /** 25 * Cluster finder for a z plane. It maintains a map of 26 * clusters of type ZPlane1 indexed by position so 27 * the clusters near a track can be retrieved quickly. 28 *<p> 29 * A track is defined to be near a cluster if the chi-square difference 30 * between the corresponding hit measurement and prediction is less 31 * than _max_chsq_diff. 32 * 33 *@author Norman A. Graf 34 *@version 1.0 35 * 36 */ 37 public class ClusFindZPlane1 extends ClusterFindManager 38 { 39 40 // static methods 41 42 // 43 44 /** 45 *Return a String representation of the class' type name. 46 *Included for completeness with the C++ version. 47 * 48 * @return A String representation of the class' type name. 49 */ 50 public static String typeName() 51 { return "ClusFindZPlane1"; } 52 53 // 54 55 /** 56 *Return a String representation of the class' type name. 57 *Included for completeness with the C++ version. 58 * 59 * @return A String representation of the class' type name. 60 */ 61 public static String staticType() 62 { return typeName(); } 63 64 65 // attributes 66 67 // surface 68 private SurfZPlane _szp; 69 70 // stereo angle 71 private double _wx; 72 private double _wy; 73 74 // maximum allowed chi-square difference 75 private double _max_chsq_diff; 76 77 // clusters 78 private TreeMap _clusters; 79 80 81 // methods 82 83 // 84 85 /** 86 *Construct an instance from the z location of the plane, the stereo angles 87 * for the x-y measurement, and the maximum chi-square 88 *difference which defines the nearness of a hit to a track. 89 * 90 * @param zpos The z position of the z plane. 91 * @param wx The stereo angle for the x measurement. 92 * @param wy The stereo angle for the y measurement. 93 * @param max_chsq_diff The maximum chi-square for a track-hit association. 94 */ 95 public ClusFindZPlane1(double zpos, double wx, double wy, double max_chsq_diff) 96 { 97 _clusters = new TreeMap(); //use a TreeMap to automatically sort 98 _szp = new SurfZPlane(zpos); 99 _wx = wx; 100 _wy = wy; 101 _max_chsq_diff = max_chsq_diff; 102 } 103 104 // 105 106 /** 107 *Add a cluster to this ClusterFindManager. 108 * The cluster must be of type ClusCylPhi or ClusCylPhiZ. 109 * 110 * @param clus The Cluster to add. 111 * @return 0 if successful. 112 */ 113 public int addCluster( Cluster clus) 114 { 115 // declare the key value 116 double keyval = 0.; 117 118 // Extract the cluster position depending on type 119 if ( clus.type().equals(ClusZPlane1.staticType()) ) 120 { 121 ClusZPlane1 clu = ( ClusZPlane1) clus; 122 Assert.assertTrue( clu.surface().equals(_szp) ); 123 Assert.assertTrue( clu.wX() == _wx ); 124 Assert.assertTrue( clu.wY() == _wy ); 125 keyval = clu.aXY(); 126 } 127 else 128 { 129 Assert.assertTrue(false); 130 System.exit(1); 131 } 132 133 // Check there is no other cluster at this position. 134 Double key = new Double(keyval); 135 if ( _clusters.containsKey(key)) 136 { 137 Assert.assertTrue(false); 138 System.exit(2); 139 } 140 // Store the cluster. 141 _clusters.put(key, clus); 142 return 0; 143 144 145 146 } 147 148 // 149 150 /** 151 *Drop all clusters from this manager. 152 * 153 */ 154 public void dropClusters() 155 { 156 _clusters.clear(); 157 } 158 159 // 160 161 /** 162 *Return the surface. 163 * 164 * @return The Surface associated to this manager. 165 */ 166 public Surface surface() 167 { 168 return _szp; 169 } 170 171 // 172 173 /** 174 *Return all the clusters. 175 * 176 * @return The list of clusters managed by this manager. 177 */ 178 public List clusters() 179 { 180 // Create the list of clusters. 181 List clusters = new ArrayList(); 182 183 // Loop over clusters and add to output list. 184 185 for ( Iterator iclu=_clusters.values().iterator(); iclu.hasNext(); ) 186 clusters.add( iclu.next() ); 187 188 return clusters; 189 190 } 191 192 // 193 194 195 196 /** 197 *Return all the clusters near a track at the surface. Nearness is delimited by the 198 *maximum chi-squared between the track prediction and the cluster measurement. 199 * 200 * Clusters have been ordered by axy. 201 * The nearby subset is returned in the same order. 202 * 203 * @param tre The ETrack for which to return clusters. 204 * @return A list of clusters near the track tre. 205 */ 206 public List clusters( ETrack tre) 207 { 208 // Create the list of clusters. 209 List clusters = new ArrayList(); 210 // Check the track surface. 211 if ( !tre.surface().equals(_szp) ) 212 { 213 Assert.assertTrue(false); 214 return clusters; 215 } 216 217 // If there are no clusters, return the empty list. 218 if ( _clusters.size() == 0 ) 219 { 220 return clusters; 221 } 222 223 // Fetch the predicted position. 224 double value = _wx*tre.vector(SurfZPlane.IX) + 225 _wy*tre.vector(SurfZPlane.IY); 226 227 228 //for time being loop over all the clusters. 229 // need to be smarter later 230 231 for(Iterator it = _clusters.values().iterator(); it.hasNext(); ) 232 { 233 //get the cluster 234 Cluster clu = (Cluster) it.next(); 235 // is cluster within range? 236 if (chsq_diffzp1(clu,tre) < _max_chsq_diff ) 237 { 238 // if so add it to the list 239 clusters.add( clu ); 240 } 241 } 242 243 244 245 /* 246 // Fetch first cluster after the prediction. 247 248 ClusterMap::const_iterator iclu1 = _clusters.lower_bound(value); 249 250 // Loop over clusters from this and above. 251 // If cluster is close, add it to the list; otherwise exit loop. 252 253 ClusterMap::const_iterator iclu = iclu1; 254 for(iclu = iclu1 ; iclu != _clusters.end(); ++iclu ) { 255 ClusterPtr pclu = (*iclu).second; 256 if ( chsq_diffzp1(pclu,tre) > _max_chsq_diff ) break; 257 clusters.push_back( pclu ); 258 } 259 260 // We have checked all clusters in the range (iclu1, +). 261 // Next go backwards from iclu1. 262 iclu = iclu1; 263 if( iclu == _clusters.begin() ) return clusters; 264 iclu--; 265 while ( true ) { 266 ClusterPtr pclu = (*iclu).second; 267 if ( chsq_diffzp1(pclu,tre) > _max_chsq_diff ) break; 268 clusters.push_front( pclu ); 269 // decrement iterator; check if the begining is reached 270 if ( iclu == _clusters.begin() ) break; 271 iclu--; 272 } 273 */ 274 // Return the nearby clusters. 275 return clusters; 276 } 277 278 279 /** 280 * Return the maximum chi-square difference which defines a hit to be near a track. 281 * 282 * @return The maximum chi-square for a track-hit association. 283 */ 284 public double maxChsqDiff() 285 { 286 return _max_chsq_diff; 287 } 288 289 // 290 291 /** 292 *Return a String representation of the class' type name. 293 *Included for completeness with the C++ version. 294 * 295 * @return A String representation of the class' type name. 296 */ 297 public String type() 298 { 299 return staticType(); 300 } 301 302 // 303 304 /** 305 *output stream 306 * 307 * @return A String representation of this instance. 308 */ 309 public String toString() 310 { 311 StringBuffer sb = new StringBuffer("1D Cluster finder for \n" + _szp +"\n"); 312 sb.append("wx weight is " + _wx + ".\n" ); 313 sb.append("wy weight is " + _wy + ".\n" ); 314 sb.append("Maximum chi-square difference is " 315 + _max_chsq_diff + ".\n"); 316 return sb.toString(); 317 } 318 319 //********************************************************************** 320 // Helper functions. 321 //********************************************************************** 322 323 // Calculate the chi-square difference between a cluster and a track. 324 // It is assumed the cluster generates exactly one prediction and that 325 // this prediction has one dimension. 326 327 private static double chsq_diffzp1( Cluster clu, ETrack tre) 328 { 329 330 // Fetch the hit predictions. 331 List hits = clu.predict(tre, clu); 332 333 // Check there is one hit. 334 Assert.assertTrue( hits.size() == 1 ); 335 336 // Fetch the hit. 337 Hit hit = (Hit) hits.get(0); 338 339 // Check the hit dimension. 340 Assert.assertTrue( hit.size() == 1 ); 341 342 // Fetch the difference between prediction and measurement. 343 double diff = hit.differenceVector().get(0); 344 345 // Fetch the measurement error and the prediction error. 346 double emeas = hit.measuredError().get(0,0); 347 double epred = hit.predictedError().get(0,0); 348 349 // Calculate and return chi-square difference. 350 return diff*diff/(emeas+epred); 351 352 } 353 354 }