All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups
TrackZVertexGrouping.cc
Go to the documentation of this file.
1 #include "TrackZVertexGrouping.h"
2 
3 // #include <iostream>
4 // #include <cmath>
5 // #include <functional>
6 // #include <algorithm>
7 
8 
9 #include <lcio.h>
10 #include <IMPL/LCCollectionVec.h>
11 #include <EVENT/Track.h>
12 #include <IMPL/ReconstructedParticleImpl.h>
13 #include <IMPL/VertexImpl.h>
14 
15 // #include <UTIL/BitField64.h>
16 // #include <UTIL/ILDConf.h>
17 #include <UTIL/Operators.h>
18 #include <UTIL/LCTOOLS.h>
19 
20 // ----- include for verbosity dependend logging ---------
21 #include "marlin/VerbosityLevels.h"
22 
23 #include <marlin/AIDAProcessor.h>
24 #include <marlin/Global.h>
25 
26 #include <AIDA/IHistogramFactory.h>
27 
28 //---- ROOT -----
29 #include "TH1F.h"
30 
31 using namespace lcio ;
32 using namespace marlin ;
33 
35 
36 //=========================================================================================
37 
38 /// helper struct for clustering tracks
39 
40 namespace {
41 
42  struct TrackGroup {
43 
44  std::list<Track*> tracks{} ;
45  double z0Significance=0. ;
46 
47  TrackGroup( Track* trk){
48  tracks.push_back( trk ) ;
49  z0Significance = trk->getZ0() / trk->getCovMatrix()[ 9 ] ; // 9 should be index of sigma_z0 !!
50  }
51 
52  // merge other group into this - after this the other group is emtpy
53  void merge( TrackGroup& other ){
54  tracks.merge( other.tracks ) ;
55 
56  //FIXME: re-compute the Z0 significance - can this be made more efficient ?
57  int ntrk = 0 ;
58  double z0SigMean = 0.;
59 
60  for(auto trk : tracks ){
61  z0SigMean += ( trk->getZ0() / trk->getCovMatrix()[ 9 ] ) ;
62  ++ntrk;
63  }
64  z0Significance = z0SigMean / ntrk ;
65  }
66  } ;
67 
68  std::ostream& operator<<( std::ostream& os, const TrackGroup& grp ){
69 
70  os << " group with " << grp.tracks.size() << " elements - z0Significance = " << grp.z0Significance << std::endl ;
71  for( auto trk : grp.tracks ){
72  os << " - trk: " << lcshort( trk ) << std::endl ;
73  }
74  return os ;
75  }
76 }
77 //=========================================================================================
78 
79 TrackZVertexGrouping::TrackZVertexGrouping() : Processor("TrackZVertexGrouping") {
80 
81  // modify processor description
82  _description = "TrackZVertexGrouping: group tracks based on their Z0 significance";
83 
84  // register steering parameters: name, description, class-variable, default value
85  registerInputCollection( LCIO::TRACK,
86  "TrackCollection" ,
87  "Name of the Track input collection" ,
89  std::string("MarlinTrkTracks")
90  );
91 
92 
93  registerOutputCollection( LCIO::RECONSTRUCTEDPARTICLE,
94  "TrackGroupPFOs" ,
95  "Name of the ReconstructedParticle output collection" ,
97  std::string("TrackGroupPFOs")
98  );
99 
100  registerOutputCollection( LCIO::VERTEX,
101  "TrackGroupVertices",
102  "Name of the Vertex output collection" ,
104  std::string("TrackGroupVertices")
105  );
106 
107  registerProcessorParameter("Z0SignificanceCut",
108  "Cut for merging track groups in Z0 significance",
110  float(1.7) );
111 
112 }
113 
114 
115 
117 
118  streamlog_out(DEBUG) << " init called " << std::endl ;
119 
120  // usually a good idea to
121  printParameters() ;
122 
123  _nRun = 0 ;
124  _nEvt = 0 ;
125 
126 }
127 
128 
130 
131  _nRun++ ;
132 }
133 
134 
135 
136 void TrackZVertexGrouping::processEvent( LCEvent * evt ) {
137 
138  streamlog_out(DEBUG2) << " process event: " << evt->getEventNumber()
139  << " in run: " << evt->getRunNumber() << std::endl ;
140 
141  // get the Track collection from the event if it exists
142  LCCollection* colTrk = nullptr ;
143 
144  try{
145  colTrk = evt->getCollection( _colNameTracks ) ;
146  }
147  catch(lcio::Exception&){
148  streamlog_out( DEBUG6 ) << " collection " << _colNameTracks
149  << " not found in event - nothing to do ... " << std::endl ;
150  }
151 
152  if( colTrk->getTypeName() != LCIO::TRACK ) {
153 
154  streamlog_out( ERROR ) << " collection " << _colNameTracks
155  << " not of type LCIO::TRACK " << std::endl ;
156 
157  colTrk = nullptr ;
158  }
159 
160  if( colTrk == nullptr )
161  return ;
162 
163 
164 
165  int nTrkTotal = colTrk->getNumberOfElements() ;
166 
167 
168  std::vector<Track*> tracks ;
169  tracks.reserve( nTrkTotal ) ;
170 
171  // copy all relevant tracks to a vector first
172  for(int i=0; i< nTrkTotal ; ++i){
173 
174  Track* trk = dynamic_cast<Track*>( colTrk->getElementAt( i ) ) ;
175 
176  // could apply track quality criteria here ...
177  if( true ){
178 
179  tracks.push_back( trk ) ;
180  }
181  }
182 
183 
184  // ========================================================================================
185  // list of groups - initially all tracks
186  std::list< TrackGroup > groups ;
187  for( auto trk : tracks ){
188  groups.emplace_back( TrackGroup( trk ) ) ;
189  }
190 
191  // sort wrt ascending z0 significance
192  groups.sort( [](TrackGroup& a, TrackGroup& b) {return a.z0Significance < b.z0Significance ; } ) ;
193 
194  //=========================================================================================
195 
196  bool keepGoing = true ;
197 
198  while( keepGoing ) {
199 
200  // loop over all neighboring pairs of groups:
201  double deltaMin = 1.e9 ;
202  std::list< TrackGroup >::iterator smallestDistGroup = groups.end() ;
203 
204  auto gEnd = groups.end() ;
205  std::advance( gEnd , - 1 ) ; // end loop one before the last
206  for( auto gIt = groups.begin() ; gIt != gEnd ; ++gIt ) {
207 
208  auto nextGrp = gIt ;
209  std::advance( nextGrp, 1 ) ;
210  double deltaZ0Sig = std::fabs( gIt->z0Significance - nextGrp->z0Significance ) ;
211  if( deltaZ0Sig < deltaMin ) {
212  deltaMin = deltaZ0Sig ;
213  smallestDistGroup = gIt ;
214  }
215  }
216  if( smallestDistGroup == groups.end() ){
217  keepGoing = false;
218  break ;
219  }
220 
221  // now merge the two groups w/ smallest difference in z0Sigma
222  if( deltaMin < _z0SignificanceCut ){
223 
224  auto nextGrp = smallestDistGroup ;
225  std::advance( nextGrp, 1 ) ;
226 
227  smallestDistGroup->merge( *nextGrp ) ;
228 
229  // and remove the empty group from the list
230  groups.erase( nextGrp ) ;
231 
232  } else { // we are done
233 
234  keepGoing = false;
235  break ;
236  }
237 
238  }
239 
240  //=========================================================================================
241  // some debug printout:
242 
243  streamlog_out( DEBUG3 ) << " ============================================================== " << std::endl
244  << " found " << groups.size() << " groups " << std::endl ;
245  for(auto grp : groups ) {
246 
247  streamlog_out( DEBUG3 ) << grp << std::endl ;
248  }
249 
250 
251  // create output collections:
252 
253  LCCollectionVec* pfos = new LCCollectionVec( LCIO::RECONSTRUCTEDPARTICLE ) ;
254  LCCollectionVec* vertices = new LCCollectionVec( LCIO::VERTEX ) ;
255 
256  evt->addCollection( pfos, _colNameTrkGroupPFOs ) ;
257  evt->addCollection( vertices, _colNameTrkGroupVertices ) ;
258 
259  for(auto grp : groups ) {
260 
261  IMPL::ReconstructedParticleImpl* pfo = new IMPL::ReconstructedParticleImpl ;
262 
263  //FIXME: simplistic mean of z0
264  double z0Mean = 0. ;
265  int nTrk=0;
266  for(auto trk : grp.tracks){
267  pfo->addTrack( trk ) ;
268  z0Mean += trk->getZ0() ;
269  ++nTrk ;
270  }
271  z0Mean /= nTrk ;
272 
273  pfos->addElement( pfo ) ;
274 
275  IMPL::VertexImpl* vtx = new IMPL::VertexImpl ;
276  vtx->setAssociatedParticle( pfo ) ;
277  vtx->setPosition( 0., 0., z0Mean ) ;
278  //FIXME: compute a meaningful covariance/error for the position
279 
280  vertices->addElement( vtx ) ;
281 
282  }
283 
284  //=========================================================================================
285  _nEvt ++ ;
286 
287 }
288 
289 
290 
291 void TrackZVertexGrouping::check( LCEvent* /*evt*/) {
292 
293  streamlog_out( DEBUG ) << " --- check called ! " << std::endl ;
294 
295 
296  // create some histograms with beta vs momentum for charged particles
297 
298  if( isFirstEvent() ){
299 
300  // this creates a directory for this processor ....
301  AIDAProcessor::histogramFactory( this ) ;
302 
303  // _h.resize(5) ;
304  // int nBins = 100 ;
305  // _h[0] = new TH2F( "hbetaFirstHitsChrg", "beta vs momentum - first hit - charged", nBins, .1 , 10., nBins, 0.93 , 1.03 ) ;
306  // _h[1] = new TH2F( "hbetaCloseHitsChrg", "beta vs momentum - closest hits - charged", nBins, .1 , 10., nBins, 0.93 , 1.03 ) ;
307 
308  // _h[2] = new TH2F( "hbetaFirstHitsNeut", "beta vs momentum - first hit - neutral", nBins, .1 , 10., nBins, 0.93 , 1.03 ) ;
309  // _h[3] = new TH2F( "hbetaCloseHitsNeut", "beta vs momentum - closest hits - neutral", nBins, .1 , 10., nBins, 0.93 , 1.03 ) ;
310 
311  // _h[4] = new TH2F( "hbetaLastTrkHit", "beta vs momentum - last tracker hit", nBins, .1 , 10., nBins, 0.93 , 1.03 ) ;
312 
313  }
314 
315 }
316 
318 
319 
320  streamlog_out(MESSAGE) << "TrackZVertexGrouping::end() " << name()
321  << " processed " << _nEvt << " events in " << _nRun << " runs "
322  << std::endl ;
323 
324 }
325 
326 
327 //*******************************************************************************************************
virtual void processRunHeader(LCRunHeader *run)
Called for every run.
std::string _colNameTracks
Input collection name with Tracks.
Group Tracks into clusters with consistent z-positions of their vertex, based on the Z0 significance...
std::string _colNameTrkGroupVertices
virtual void init()
Called at the begin of the job before anything is read.
TrackZVertexGrouping aTrackZVertexGrouping
std::vector< LCCollection * > LCCollectionVec
Definition: SiStripClus.h:55
virtual void end()
Called after data processing for clean up.
virtual void check(LCEvent *evt)
virtual void processEvent(LCEvent *evt)
Called for every event - the working horse.