#include "Hitpattern.h"
#include "Hit.h"
#include "WirePlane.h"
#include "PatternTree.h"
#include "TError.h"
#include "TMath.h"
#include "MWDC.h"
#include <iostream>
#include <stdexcept>
#include <algorithm>
using namespace std;
typedef std::vector<TreeSearch::Hit*>::size_type vsiz_t;
ClassImp(TreeSearch::Hitpattern)
namespace TreeSearch {
Hitpattern::Hitpattern( const PatternTree& pt )
: fNlevels(pt.GetNlevels()), fNplanes(pt.GetNplanes()), fScale(0),
fOffset(0.5*pt.GetWidth()), fPattern(0)
#ifdef TESTCODE
, fMaxhitBin(0)
#endif
{
Init( pt.GetWidth() );
}
Hitpattern::Hitpattern( UInt_t nlevels, UInt_t nplanes, Double_t width )
: fNlevels(nlevels), fNplanes(0), fScale(0), fOffset(0.5*width), fPattern(0)
#ifdef TESTCODE
, fMaxhitBin(0)
#endif
{
static const char* const here = "TreeSearch::Hitpattern";
if( nplanes == 0 || nplanes > 16 || fNlevels == 0 || fNlevels > 16 ) {
::Error( here, "Illegal number of planes or tree levels: %d %d.\n"
"Both must be 0 < n <= 16.", nplanes, nlevels );
} else if( width < 1e-2 ) {
::Error( here, "Illegal detector width %lf. Must be >= +1cm.", width );
} else {
fNplanes = nplanes;
Init( width );
}
}
void Hitpattern::Init( Double_t width )
{
assert( width >= 1e-2 );
fScale = GetNbins() / width;
fBinWidth = 1.0/fScale;
try {
fPattern = new Bits*[fNplanes];
UInt_t nbins2 = 2*GetNbins();
for( UInt_t i=0; i<fNplanes; i++ )
fPattern[i] = new Bits( nbins2 );
fHits.resize( fNplanes*GetNbins() );
}
catch ( std::bad_alloc ) {
::Error( "Hitpattern::Hitpattern", "Out of memory trying to construct "
"new Hitpattern object. Call expert." );
throw;
}
}
Hitpattern::Hitpattern( const Hitpattern& orig )
try
: fNlevels(orig.fNlevels), fNplanes(orig.fNplanes),
fScale(orig.fScale), fBinWidth(orig.fBinWidth), fOffset(orig.fOffset),
fPattern(0), fHits(orig.fHits), fHitList(orig.fHitList)
#ifdef TESTCODE
, fMaxhitBin(orig.fMaxhitBin)
#endif
{
if( fNplanes > 0 ) {
fPattern = new Bits*[fNplanes];
for( UInt_t i=fNplanes; i--; )
fPattern[i] = new Bits(*orig.fPattern[i]);
}
assert( fHits.size() == fNplanes*GetNbins() );
}
catch ( std::bad_alloc ) {
::Error( "Hitpattern::Hitpattern", "Out of memory trying to copy Hitpattern "
"object. Call expert." );
throw;
}
Hitpattern& Hitpattern::operator=( const Hitpattern& rhs )
{
if( this != &rhs ) {
fNlevels = rhs.fNlevels;
fNplanes = rhs.fNplanes;
fScale = rhs.fScale;
fBinWidth= rhs.fBinWidth;
fOffset = rhs.fOffset;
delete fPattern; fPattern = 0;
if( fNplanes > 0 ) {
fPattern = new Bits*[fNplanes];
for( UInt_t i=fNplanes; i--; )
fPattern[i] = new Bits(*rhs.fPattern[i]);
}
fHits = rhs.fHits;
assert( fHits.size() == fNplanes*GetNbins() );
fHitList = rhs.fHitList;
#ifdef TESTCODE
fMaxhitBin = rhs.fMaxhitBin;
#endif
}
return *this;
}
Hitpattern::~Hitpattern()
{
for( UInt_t i=fNplanes; i; )
delete fPattern[--i];
delete [] fPattern;
}
inline
void Hitpattern::AddHit( UInt_t plane, UInt_t bin, Hit* hit ) {
assert(hit);
UInt_t idx = MakeIdx( plane, bin );
fHits[idx].push_back( hit );
fHitList.push_back( idx );
#ifdef TESTCODE
if( fMaxhitBin < (UInt_t)fHits[idx].size() )
fMaxhitBin = fHits[idx].size();
#endif
}
void Hitpattern::Clear( Option_t* )
{
for( UInt_t i=fNplanes; i; )
fPattern[--i]->FastClear();
for( vector<UInt_t>::iterator it = fHitList.begin(); it != fHitList.end();
++it ) {
UInt_t idx = *it;
assert( idx < fHits.size());
fHits[idx].clear();
}
fHitList.clear();
#ifdef TESTCODE
fMaxhitBin = 0;
#endif
}
#ifdef TESTCODE
UInt_t Hitpattern::GetBinsSet() const
{
UInt_t n = 0, nbins = GetNbins();
for( UInt_t i=fNplanes; i; ) {
n += fPattern[--i]->CountBits( nbins );
}
return n;
}
#endif
void Hitpattern::SetPositionRange( Double_t start, Double_t end,
UInt_t plane, Hit* hit )
{
assert( plane<fNplanes && start<=end );
Int_t hi = TMath::FloorNint( fScale*end );
if( hi < 0 ) return;
Int_t lo = TMath::FloorNint( fScale*start );
Int_t nbins = GetNbins();
if( lo >= nbins ) return;
if( lo < 0 )
lo = 0;
if( hi >= nbins )
hi = nbins-1;
for( Int_t i = lo; i <= hi; ++i )
AddHit( plane, i, hit );
while (true) {
fPattern[plane]->SetBitRange( lo+nbins, hi+nbins );
nbins >>= 1;
if( nbins == 0 ) break;
lo >>= 1;
hi >>= 1;
}
}
Int_t Hitpattern::ScanHits( WirePlane* A, WirePlane* B )
{
if( !A ) return 0;
UInt_t planeA = A->GetPlaneNum();
assert( planeA < fNplanes );
Double_t maxdist = 0.0;
UInt_t planeB = fNplanes;
if( B ) {
maxdist = A->GetMaxSlope() * (B->GetZ() - A->GetZ());
planeB = B->GetPlaneNum();
assert( planeB < fNplanes );
}
bool do_single_hits =
( A->GetMWDC()->TestBit(MWDC::kPairsOnly) == kFALSE || B == 0 );
Int_t nhits = 0;
HitPairIter it( A->GetHits(), B ? B->GetHits() : 0, maxdist );
while( it ) {
nhits++;
Hit* hitA = static_cast<Hit*>((*it).first);
Hit* hitB = static_cast<Hit*>((*it).second);
assert( hitA || hitB );
if( hitA && hitB ) {
int set = 0, bitA, bitB;
Double_t posA, posB;
for( int i = 4; i; ) { --i;
if( i&2 ) { posA = hitA->GetPosL(); bitA = 8; }
else { posA = hitA->GetPosR(); bitA = 4; }
if( i&1 ) { posB = hitB->GetPosL(); bitB = 2; }
else { posB = hitB->GetPosR(); bitB = 1; }
if( TMath::Abs( posA-posB ) <= maxdist ) {
if( (bitA & set) == 0 ) {
SetPosition( posA+fOffset, hitA->GetResolution(), planeA, hitA );
if( hitA->GetDriftDist() == 0 )
set |= 12;
else
set |= bitA;
}
if( (bitB & set) == 0 ) {
SetPosition( posB+fOffset, hitB->GetResolution(), planeB, hitB );
if( hitB->GetDriftDist() == 0 )
set |= 3;
else
set |= bitB;
}
}
}
}
else if( do_single_hits ) {
if( hitA ) {
SetPosition( hitA->GetPosL()+fOffset, hitA->GetResolution(),
planeA, hitA );
SetPosition( hitA->GetPosR()+fOffset, hitA->GetResolution(),
planeA, hitA );
} else {
SetPosition( hitB->GetPosL()+fOffset, hitB->GetResolution(),
planeB, hitB );
SetPosition( hitB->GetPosR()+fOffset, hitB->GetResolution(),
planeB, hitB );
}
}
++it;
}
return nhits;
}
void Hitpattern::Print( Option_t* ) const
{
}
void Bits::ResetBitRange( UInt_t lo, UInt_t hi )
{
if( hi<lo ) return;
UChar_t mask = ~((1U<<(lo&7))-1);
lo >>= 3;
if( lo >= fNbytes ) return;
UChar_t mask2 = (1U<<((hi&7)+1))-1;
hi >>= 3;
if( hi >= fNbytes ) {
hi = fNbytes-1;
mask2 = 0xFF;
}
if( lo < hi ) {
fAllBits[hi] &= (0xFF ^ mask2);
memset( fAllBits+lo+1, 0, hi-lo-1 );
} else {
mask &= mask2;
}
fAllBits[lo] &= (0xFF ^ mask);
}
void Bits::SetBitRange( UInt_t lo, UInt_t hi )
{
if( hi<lo ) return;
SetBitNumber( hi );
if( lo==hi ) return;
UChar_t mask = ~((1U<<(lo&7))-1);
UChar_t mask2 = (1U<<(hi&7))-1;
lo >>= 3;
hi >>= 3;
if( lo < hi ) {
fAllBits[hi] |= mask2;
memset( fAllBits+lo+1, 0xFF, hi-lo-1 );
} else {
mask &= mask2;
}
fAllBits[lo] |= mask;
}
}