View Javadoc

1   package org.lcsim.recon.tracking.gtrfit;
2   
3   import java.util.TreeSet;
4   import java.util.List;
5   import java.util.ArrayList;
6   import java.util.Iterator;
7   import java.util.Collections;
8   
9   import org.lcsim.recon.tracking.trfutil.Assert;
10  
11  import org.lcsim.recon.tracking.trfbase.Propagator;
12  import org.lcsim.recon.tracking.trffit.AddFitter;
13  import org.lcsim.recon.tracking.trffit.AddFitKalman;
14  import org.lcsim.recon.tracking.gtrbase.GTrack;
15  import org.lcsim.recon.tracking.gtrbase.GTrackState;
16  import org.lcsim.recon.tracking.gtrbase.FitStatus;
17  import org.lcsim.recon.tracking.trfbase.ETrack;
18  import org.lcsim.recon.tracking.trfbase.PropStat;
19  import org.lcsim.recon.tracking.trfbase.Hit;
20  import org.lcsim.recon.tracking.trfbase.TrackError;
21  import org.lcsim.recon.tracking.trfbase.Surface;
22  import org.lcsim.recon.tracking.trfbase.Cluster;
23  import org.lcsim.recon.tracking.trfbase.PropDir;
24  
25  import org.lcsim.recon.tracking.trffit.HTrack;
26  /**
27   * A class which fits a GTrack.
28   *
29   *@author Norman A. Graf
30   *@version 1.0
31   *
32   */
33  public class SimpleGTrackFitter
34  {
35      
36      //**********************************************************************
37      // Local definitions.
38      //**********************************************************************
39      
40      private static final int FORWARD = 1;
41      private static final int BACKWARD = -1;
42      private static final double ERRFAC = 10.;
43      
44      
45      // attributes
46      
47      // Propagator.
48      private Propagator _prop;
49      
50      // Fit order.
51      private int _order;
52      
53      // Add fitter.
54      private AddFitter _fitter;
55      
56      // Maximum chi-square.
57      private double _chsq_max;
58      
59      
60      // methods
61      
62      /**
63       *Construct an instance from a propagator, the order in which to fit, and a
64       * chi-square value on which to cut.
65       * order = fit order (1 for going out, -1 for going in)
66       *
67       * @param   prop   The Propagator to use in the fit.
68       * @param   order  The order in wich to fit (1 for going out, -1 for going in).
69       * @param   chsq_max The maximum value of chi-square to allow for a hit.
70       */
71      public  SimpleGTrackFitter( Propagator prop, int order,
72              double chsq_max)
73      {
74          _prop = prop;
75          _order = order;
76          _fitter =  new AddFitKalman();
77          _chsq_max = chsq_max;
78          if ( _order!=FORWARD && _order!=BACKWARD )
79          {
80              throw new IllegalArgumentException("Fit order must be FORWARD or BACKWARD!");
81          }
82      }
83      
84      
85      /**
86       *Fit a track.
87       *
88       * @param   gtr The GTrack to fit.
89       * @return 0 for successful fit.
90       */
91      public int fit(GTrack gtr)
92      {
93          
94          // Extract list of states.
95          TreeSet oldstates = gtr.states();
96          
97          // Require track to have at least one valid state.
98          if ( oldstates.size() < 1 )
99          {
100             return 1;
101         }
102         
103         // Extract starting track and error.
104         GTrackState state0 = new GTrackState();
105         if ( _order == FORWARD ) state0  = (GTrackState) oldstates.first();
106         if ( _order == BACKWARD ) state0 = (GTrackState) oldstates.last();
107         
108         // The first state must be valid.
109         Assert.assertTrue( state0.isValid() );
110         if ( ! state0.isValid() )
111         {
112             return 2;
113         }
114         
115         double s0 = state0.s();
116         ETrack tre0 = state0.track();
117         //Starting surface
118         Surface srf0 = tre0.surface();
119         // Increase error.
120         {
121             TrackError err = tre0.error();
122             for ( int j=0; j<5; ++j )
123             {
124                 for ( int i=0; i<=j; ++i )
125                 {
126                     err.set(i,j, err.get(i,j)*ERRFAC );
127                 }
128             }
129             tre0.setError(err);
130         }
131         
132         // Build list of clusters, preserving or reversing order.
133         
134         List clusters = new ArrayList();
135         
136         for ( Iterator istate=oldstates.iterator(); istate.hasNext(); )
137         {
138             clusters.add( ((GTrackState) istate.next() ).cluster() );
139         }
140         if ( _order == BACKWARD ) Collections.reverse(clusters);
141         
142         // Build starting HTrack.
143         HTrack trh = new HTrack(tre0);
144         
145         // New GTrack state list.
146         TreeSet newstates = new TreeSet();
147         
148         //
149         // Loop over states and add each cluster in turn to the fit.
150         // If cluster does not exist, interact track at the state surface
151         //
152         double spath = 0.0;
153         boolean first = true;
154         for ( Iterator clusit = clusters.iterator(); clusit.hasNext(); )
155         {
156             
157             // Get the TRF++ cluster.
158             
159             Cluster clus = (Cluster) clusit.next();
160             double ds1 = 0;
161             double ds2 = 0;
162             
163             // Propagate the fitted track to the cluster surface.
164             Surface srf = clus.surface().newSurface();
165             Assert.assertTrue( srf != null );
166             if( !first || !srf.pureEqual(srf0) )
167             {
168                 PropStat pstat =
169                         trh.propagate( _prop, srf, PropDir.NEAREST );
170                 if ( ! pstat.success())
171                 {
172                     return 3;
173                 }
174                 ds1 = pstat.pathDistance();
175             }
176             
177             // Extract the hit.
178             List hits = clus.predict( trh.newTrack(), clus );
179             Assert.assertTrue( hits.size() == 1 );
180             Hit hit = (Hit) hits.get(0);
181             
182             // Propagate the fitted track to the hit surface.
183             Surface srf2 = (hit.surface()).newSurface();
184             if( !srf2.pureEqual(srf) )
185             {
186                 Assert.assertTrue( srf2 != null );
187                 PropStat pstat = trh.propagate( _prop, srf2, PropDir.NEAREST );
188                 if ( ! pstat.success())
189                 {
190                     return 4;
191                 }
192                 ds2 = pstat.pathDistance();
193             }
194             
195             // Update the path distance.
196             double ds = ds1 + ds2;
197             boolean ds_ok = ( _order == FORWARD && ds >= 0.0) ||
198                     ( _order == BACKWARD && ds <= 0.0);
199             if ( ! ds_ok )
200             {
201                 return 5;
202             }
203             spath += ds;
204             
205             // Fit with the new hit.
206             int stat = _fitter.addHit(trh,hit);
207             
208             // bad fit
209             if ( stat != 0 )
210             {
211                 return 6;
212             }
213             // good fit, but bad chi-squared
214             if ( trh.chisquared() > _chsq_max )
215             {
216                 return 7;
217             }
218             
219             // Add new GTrackState.
220             
221             FitStatus fstat = FitStatus.INVALID;
222             // If there are no more clusters this fit is OPTIMAL at this state
223             if ( ! clusit.hasNext() )
224             {
225                 fstat = FitStatus.OPTIMAL;
226             }
227             else
228             {
229                 if ( _order == 1 ) fstat = FitStatus.FORWARD;
230                 if ( _order == -1 )fstat = FitStatus.BACKWARD;
231             }
232             
233             ETrack tre = trh.newTrack();
234             double chsq = trh.chisquared();
235             newstates.add( new GTrackState( spath, tre, fstat, chsq, clus ));
236             
237             //	}
238             
239             first = false;
240             
241         }  // end loop over clusters.
242         
243         // Construct new GTrack.
244         gtr.update(newstates);
245         
246         return 0;
247     }
248     
249     
250     /**
251      *output stream
252      *
253      * @return A String representation of this instance.
254      */
255     public String toString()
256     {
257         return "SimpleGTrackFitter: " +
258                 "\nPropagator: " + _prop +
259                 "\nFitter: " + _fitter +
260                 "\n with chsq_max = " + _chsq_max;
261     }
262 }