ROOT logo
//*-- Author :    Ole Hansen, Jefferson Lab   27-Jun-2007

///////////////////////////////////////////////////////////////////////////////
//                                                                           //
// TreeSearch::Hit                                                           //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////

#include "Hit.h"
#include "TSeqCollection.h"
#include "WirePlane.h"
#include "Road.h"

#include <iostream>

using std::cout;
using std::endl;
using std::make_pair;

ClassImp(TreeSearch::Hit)
ClassImp(TreeSearch::MCHit)
ClassImp(TreeSearch::HitPairIter)
ClassImp(TreeSearch::HitSet)

namespace TreeSearch {

//_____________________________________________________________________________
void Hit::Print( Option_t* opt ) const
{
  // Print hit info

  cout << "Hit: wire=" << GetWireNum()
       << "/" << (fWirePlane ? fWirePlane->GetName() : "??")
       << " wpos="     << GetWirePos()
       << " z="        << GetZ()
       << " res="      << GetResolution()
       << " time="     << GetDriftTime()
       << " drift="    << GetDriftDist();
  if( *opt != 'C' )
    cout << endl;
}

//_____________________________________________________________________________
Double_t Hit::ConvertTimeToDist( Double_t slope )
{
  // Convert drift time to drift distance. 'slope' is the approximate
  // slope of the track.
  // Updates the internal variables fPosL and fPosR.
  // Must be called before doing analysis of drift chamber hits.
  Double_t dist = fWirePlane->GetTTDConv()->ConvertTimeToDist(fTime, slope);
  fPosL = fPos-dist;
  fPosR = fPos+dist;
  return dist;
}

//_____________________________________________________________________________
Double_t Hit::GetZ() const
{
  // Return z-position of the wire plane of this hit

  return fWirePlane->GetZ();
}

//_____________________________________________________________________________
void MCHit::Print( Option_t* ) const
{
  // Print hit info

  Hit::Print("C");
  cout << " MCpos=" << GetMCPos()
       << endl;
}

//_____________________________________________________________________________
Double_t FitCoord::GetChi2() const
{
  // Return chi2 of the fit that used this coordinate

  return fRoad ? fRoad->GetChi2() : kBig;
}

//_____________________________________________________________________________
HitPairIter::HitPairIter( const TSeqCollection* collA,
			  const TSeqCollection* collB,
			  Double_t maxdist ) 
  : fCollA(collA), fCollB(collB), fIterA(0), fIterB(0),
    fSaveIter(0), fSaveHit(0), fMaxDist(maxdist), fStarted(kFALSE),
    fScanning(kFALSE)
{
  // Constructor

  if( !fIterA && fCollA )
    fIterA = fCollA->MakeIterator();
  if( !fIterB && fCollB ) {
    fIterB = fCollB->MakeIterator();
    if( !fSaveIter )
      fSaveIter = fCollB->MakeIterator();
  }
  // Initialize our state so we point to the first item
  Next();
}

//_____________________________________________________________________________
HitPairIter::HitPairIter( const HitPairIter& rhs )
  : fCollA(rhs.fCollA), fCollB(rhs.fCollB), fIterA(0), fIterB(0),
    fSaveIter(0), fSaveHit(rhs.fSaveHit),
    fMaxDist(fMaxDist), fStarted(rhs.fStarted), fScanning(rhs.fScanning),
    fCurrent(rhs.fCurrent), fNext(rhs.fNext)
{
  // Copy ctor

  if( fCollA ) {
    fIterA = fCollA->MakeIterator();
    *fIterA = *rhs.fIterA;
  }
  if( fCollB ) {
    fIterB = fCollB->MakeIterator();
    *fIterB = *rhs.fIterB;
    fSaveIter = fCollB->MakeIterator();
    *fSaveIter = *rhs.fSaveIter;
  }
}

//_____________________________________________________________________________
HitPairIter& HitPairIter::operator=( const HitPairIter& rhs )
{
  // Assignment operator

  if( this != &rhs ) {
    fCollA     = rhs.fCollA;
    fCollB     = rhs.fCollB;
    fMaxDist   = rhs.fMaxDist;
    fStarted   = rhs.fStarted;
    fScanning  = rhs.fScanning;
    fCurrent   = rhs.fCurrent;
    fNext      = rhs.fNext;
    delete fIterA;
    delete fIterB;
    delete fSaveIter;
    if( fCollA ) {
      fIterA = fCollA->MakeIterator();
      *fIterA = *rhs.fIterA;
    }
    if( fCollB ) {
      fIterB = fCollB->MakeIterator();
      *fIterB = *rhs.fIterB;
      fSaveIter = fCollB->MakeIterator();
      *fSaveIter = *rhs.fSaveIter;
    }
  }
  return *this;
}

//_____________________________________________________________________________
HitPairIter::~HitPairIter()
{
  // Destructor

  delete fIterA;
  delete fIterB;
  delete fSaveIter;
}


//_____________________________________________________________________________
void HitPairIter::Reset()
{
  // Reset the iterator to the start

  fStarted = fScanning = kFALSE;
  if( fIterA )
    fIterA->Reset();
  if( fIterB )
    fIterB->Reset();
  // Our initial state is to point to the first object
  Next();
}


//_____________________________________________________________________________
HitPairIter& HitPairIter::Next()
{
  // Return next pair of hits along the wire plane. If a hit in either
  // plane is unpaired (no matching hit on the other plane within maxdist)
  // then only that hit is set in the returned pair object. If both
  // hits returned are zero, then there are no more hits in either plane.

  if( !fStarted ) {
    fNext = make_pair( fIterA ? fIterA->Next() : 0, 
		       fIterB ? fIterB->Next() : 0 );
    fStarted = kTRUE;
  }

  fCurrent = fNext;
  Hit* hitA = static_cast<Hit*>( fCurrent.first );
  Hit* hitB = static_cast<Hit*>( fCurrent.second );

  if( hitA && hitB ) {
    switch( hitA->Compare(hitB,fMaxDist) ) {
    case -1: // A<B 
      fNext.first  = fIterA->Next();
      fCurrent.second = 0;
      break;
    case  1: // A>B
      fNext.second = fIterB->Next();
      fCurrent.first = 0;
      break;
    default: // A==B
      {
	// Found a pair
	Hit* nextB = static_cast<Hit*>( fIterB->Next() );
	if( !nextB || hitA->Compare(nextB,fMaxDist) < 0 ) {
	  if( fScanning ) {
	    // End of a scan of plane B with fixed hitA
	    fScanning = kFALSE;
	    // Return B to the point where we started the scan
	    *fIterB = *fSaveIter;
	    hitB = fSaveHit;
	    // Advance to the next hit in A
	    hitA = static_cast<Hit*>( fIterA->Next() );
	    // Advance B until either B >= A or B == nextB (the hit in B that
	    // ended the prior scan), whichever comes first.
	    // The Bs for which saveB <= B < nextB have been paired with the 
	    // prior A in the prior scan and so can't be considered unpaired,
	    // but they might pair with the new A, still.
	    if( hitA ) {
	      while( hitB != nextB && hitB->Compare(hitA,fMaxDist) < 0 )
		hitB = static_cast<Hit*>( fIterB->Next() );
	    } else {
	      // Of course, if there are no more hits in A, we only have to 
	      // scan the rest of the Bs.
	      hitB = nextB;
	    }
	    fNext = make_pair( hitA, hitB );

	  } else {
	    // This is the normal case: nextB > hitA (usually true for 
	    // small maxdist). So hitA/hitB are a pair, and
	    // the next hits to consider are the next ones in each plane.
	    fNext = make_pair( fIterA->Next(), nextB );
	  }
	} else {
	  // A==B and A==nextB, so more than one B matches this A.
	  // Start scanning mode where we keep hitA fixed and walk along 
	  // B as long as B==A.
	  if( !fScanning ) {
	    fScanning = kTRUE;
	    // Save the starting point of the scan. We have to save both
	    // the iterator and the object because ROOT's TIterator
	    // is rather dumb (no Current() method).
	    *fSaveIter = *fIterB;
	    fSaveHit = hitB;
	  }
	  // nextB != 0 and hitA == nextB guaranteed here, so the
	  // next iteration will give hitA==hitB again.
	  fNext.second = nextB;
	}
	break;
      }
    }
  } else if( hitA ) {
    fNext.first  = fIterA->Next();
  } else if( hitB ) {
    fNext.second = fIterB->Next();
  }

  return *this;
}

//_____________________________________________________________________________
UInt_t HitSet::GetMatchValue( const Hset_t& hits )
{
  // Return plane occupancy pattern of given hitset

  UInt_t curpat = 0;
  for( Hset_t::const_iterator it = hits.begin(); it != hits.end(); ++it )
    curpat |= 1U << (*it)->GetPlaneNum();

  return curpat;
}

//_____________________________________________________________________________
Bool_t HitSet::IsSimilarTo( const HitSet& tryset, Int_t maxdist ) const
{
  // If maxdist == 0:
  // Similar to STL includes() algorithm, but allows tryset to have additional
  // hits in a given wire plane if there is at least one included hit in that
  // plane.
  //
  // Example: the following matches, despite the extra hit in "try":
  //   this:  30/   32/40/50/51
  //   try:   --/31 32/40/50/51
  // 
  // Standard includes() implies intersection == set2.
  // This algorithm tests planepattern(intersection) == planepattern(set2)
  //
  // If maxdist > 0:
  // Same as above, but consider hits "equal" not only if they are identical
  // but also if their wire numbers are at most maxdist apart.
  //
  // Exmaple: the following two patters are "similar" with maxdist = 1:
  //   this:  30/32/40/50/51
  //   try:   31/32/40/50/51
  //
  // This mode can be used to build "clusters" of patterns.

  assert( tryset.plane_pattern );

  Hset_t::const_iterator ihits = hits.begin();
  Hset_t::const_iterator ehits = hits.end();
  Hset_t::const_iterator itry  = tryset.hits.begin();
  Hset_t::const_iterator etry  = tryset.hits.end();
  //  Hset_t::key_compare    comp  = hits.key_comp();
  Hit::WireDistLess comp(maxdist);

  UInt_t intersection_pattern = 0;

  while( ihits != ehits and itry != etry ) {
    if( comp(*itry, *ihits) )
      ++itry;
    else if( comp(*ihits, *itry) )
      ++ihits;
    else {
      intersection_pattern |= 1U << (*itry)->GetPlaneNum();
      ++ihits;
      ++itry;
    }
  }
  return tryset.plane_pattern == intersection_pattern;
}

///////////////////////////////////////////////////////////////////////////////

} // end namespace TreeSearch

 Hit.cxx:1
 Hit.cxx:2
 Hit.cxx:3
 Hit.cxx:4
 Hit.cxx:5
 Hit.cxx:6
 Hit.cxx:7
 Hit.cxx:8
 Hit.cxx:9
 Hit.cxx:10
 Hit.cxx:11
 Hit.cxx:12
 Hit.cxx:13
 Hit.cxx:14
 Hit.cxx:15
 Hit.cxx:16
 Hit.cxx:17
 Hit.cxx:18
 Hit.cxx:19
 Hit.cxx:20
 Hit.cxx:21
 Hit.cxx:22
 Hit.cxx:23
 Hit.cxx:24
 Hit.cxx:25
 Hit.cxx:26
 Hit.cxx:27
 Hit.cxx:28
 Hit.cxx:29
 Hit.cxx:30
 Hit.cxx:31
 Hit.cxx:32
 Hit.cxx:33
 Hit.cxx:34
 Hit.cxx:35
 Hit.cxx:36
 Hit.cxx:37
 Hit.cxx:38
 Hit.cxx:39
 Hit.cxx:40
 Hit.cxx:41
 Hit.cxx:42
 Hit.cxx:43
 Hit.cxx:44
 Hit.cxx:45
 Hit.cxx:46
 Hit.cxx:47
 Hit.cxx:48
 Hit.cxx:49
 Hit.cxx:50
 Hit.cxx:51
 Hit.cxx:52
 Hit.cxx:53
 Hit.cxx:54
 Hit.cxx:55
 Hit.cxx:56
 Hit.cxx:57
 Hit.cxx:58
 Hit.cxx:59
 Hit.cxx:60
 Hit.cxx:61
 Hit.cxx:62
 Hit.cxx:63
 Hit.cxx:64
 Hit.cxx:65
 Hit.cxx:66
 Hit.cxx:67
 Hit.cxx:68
 Hit.cxx:69
 Hit.cxx:70
 Hit.cxx:71
 Hit.cxx:72
 Hit.cxx:73
 Hit.cxx:74
 Hit.cxx:75
 Hit.cxx:76
 Hit.cxx:77
 Hit.cxx:78
 Hit.cxx:79
 Hit.cxx:80
 Hit.cxx:81
 Hit.cxx:82
 Hit.cxx:83
 Hit.cxx:84
 Hit.cxx:85
 Hit.cxx:86
 Hit.cxx:87
 Hit.cxx:88
 Hit.cxx:89
 Hit.cxx:90
 Hit.cxx:91
 Hit.cxx:92
 Hit.cxx:93
 Hit.cxx:94
 Hit.cxx:95
 Hit.cxx:96
 Hit.cxx:97
 Hit.cxx:98
 Hit.cxx:99
 Hit.cxx:100
 Hit.cxx:101
 Hit.cxx:102
 Hit.cxx:103
 Hit.cxx:104
 Hit.cxx:105
 Hit.cxx:106
 Hit.cxx:107
 Hit.cxx:108
 Hit.cxx:109
 Hit.cxx:110
 Hit.cxx:111
 Hit.cxx:112
 Hit.cxx:113
 Hit.cxx:114
 Hit.cxx:115
 Hit.cxx:116
 Hit.cxx:117
 Hit.cxx:118
 Hit.cxx:119
 Hit.cxx:120
 Hit.cxx:121
 Hit.cxx:122
 Hit.cxx:123
 Hit.cxx:124
 Hit.cxx:125
 Hit.cxx:126
 Hit.cxx:127
 Hit.cxx:128
 Hit.cxx:129
 Hit.cxx:130
 Hit.cxx:131
 Hit.cxx:132
 Hit.cxx:133
 Hit.cxx:134
 Hit.cxx:135
 Hit.cxx:136
 Hit.cxx:137
 Hit.cxx:138
 Hit.cxx:139
 Hit.cxx:140
 Hit.cxx:141
 Hit.cxx:142
 Hit.cxx:143
 Hit.cxx:144
 Hit.cxx:145
 Hit.cxx:146
 Hit.cxx:147
 Hit.cxx:148
 Hit.cxx:149
 Hit.cxx:150
 Hit.cxx:151
 Hit.cxx:152
 Hit.cxx:153
 Hit.cxx:154
 Hit.cxx:155
 Hit.cxx:156
 Hit.cxx:157
 Hit.cxx:158
 Hit.cxx:159
 Hit.cxx:160
 Hit.cxx:161
 Hit.cxx:162
 Hit.cxx:163
 Hit.cxx:164
 Hit.cxx:165
 Hit.cxx:166
 Hit.cxx:167
 Hit.cxx:168
 Hit.cxx:169
 Hit.cxx:170
 Hit.cxx:171
 Hit.cxx:172
 Hit.cxx:173
 Hit.cxx:174
 Hit.cxx:175
 Hit.cxx:176
 Hit.cxx:177
 Hit.cxx:178
 Hit.cxx:179
 Hit.cxx:180
 Hit.cxx:181
 Hit.cxx:182
 Hit.cxx:183
 Hit.cxx:184
 Hit.cxx:185
 Hit.cxx:186
 Hit.cxx:187
 Hit.cxx:188
 Hit.cxx:189
 Hit.cxx:190
 Hit.cxx:191
 Hit.cxx:192
 Hit.cxx:193
 Hit.cxx:194
 Hit.cxx:195
 Hit.cxx:196
 Hit.cxx:197
 Hit.cxx:198
 Hit.cxx:199
 Hit.cxx:200
 Hit.cxx:201
 Hit.cxx:202
 Hit.cxx:203
 Hit.cxx:204
 Hit.cxx:205
 Hit.cxx:206
 Hit.cxx:207
 Hit.cxx:208
 Hit.cxx:209
 Hit.cxx:210
 Hit.cxx:211
 Hit.cxx:212
 Hit.cxx:213
 Hit.cxx:214
 Hit.cxx:215
 Hit.cxx:216
 Hit.cxx:217
 Hit.cxx:218
 Hit.cxx:219
 Hit.cxx:220
 Hit.cxx:221
 Hit.cxx:222
 Hit.cxx:223
 Hit.cxx:224
 Hit.cxx:225
 Hit.cxx:226
 Hit.cxx:227
 Hit.cxx:228
 Hit.cxx:229
 Hit.cxx:230
 Hit.cxx:231
 Hit.cxx:232
 Hit.cxx:233
 Hit.cxx:234
 Hit.cxx:235
 Hit.cxx:236
 Hit.cxx:237
 Hit.cxx:238
 Hit.cxx:239
 Hit.cxx:240
 Hit.cxx:241
 Hit.cxx:242
 Hit.cxx:243
 Hit.cxx:244
 Hit.cxx:245
 Hit.cxx:246
 Hit.cxx:247
 Hit.cxx:248
 Hit.cxx:249
 Hit.cxx:250
 Hit.cxx:251
 Hit.cxx:252
 Hit.cxx:253
 Hit.cxx:254
 Hit.cxx:255
 Hit.cxx:256
 Hit.cxx:257
 Hit.cxx:258
 Hit.cxx:259
 Hit.cxx:260
 Hit.cxx:261
 Hit.cxx:262
 Hit.cxx:263
 Hit.cxx:264
 Hit.cxx:265
 Hit.cxx:266
 Hit.cxx:267
 Hit.cxx:268
 Hit.cxx:269
 Hit.cxx:270
 Hit.cxx:271
 Hit.cxx:272
 Hit.cxx:273
 Hit.cxx:274
 Hit.cxx:275
 Hit.cxx:276
 Hit.cxx:277
 Hit.cxx:278
 Hit.cxx:279
 Hit.cxx:280
 Hit.cxx:281
 Hit.cxx:282
 Hit.cxx:283
 Hit.cxx:284
 Hit.cxx:285
 Hit.cxx:286
 Hit.cxx:287
 Hit.cxx:288
 Hit.cxx:289
 Hit.cxx:290
 Hit.cxx:291
 Hit.cxx:292
 Hit.cxx:293
 Hit.cxx:294
 Hit.cxx:295
 Hit.cxx:296
 Hit.cxx:297
 Hit.cxx:298
 Hit.cxx:299
 Hit.cxx:300
 Hit.cxx:301
 Hit.cxx:302
 Hit.cxx:303
 Hit.cxx:304
 Hit.cxx:305
 Hit.cxx:306
 Hit.cxx:307
 Hit.cxx:308
 Hit.cxx:309
 Hit.cxx:310
 Hit.cxx:311
 Hit.cxx:312
 Hit.cxx:313
 Hit.cxx:314
 Hit.cxx:315
 Hit.cxx:316
 Hit.cxx:317
 Hit.cxx:318
 Hit.cxx:319
 Hit.cxx:320
 Hit.cxx:321
 Hit.cxx:322
 Hit.cxx:323
 Hit.cxx:324
 Hit.cxx:325
 Hit.cxx:326
 Hit.cxx:327
 Hit.cxx:328
 Hit.cxx:329
 Hit.cxx:330
 Hit.cxx:331
 Hit.cxx:332
 Hit.cxx:333
 Hit.cxx:334
 Hit.cxx:335