ROOT logo
///////////////////////////////////////////////////////////////////////////////
//                                                                           //
// TreeSearch::PatternTree                                                   //
//                                                                           //
///////////////////////////////////////////////////////////////////////////////

#include "PatternTree.h"
#include "Pattern.h"
//#include "TreeFile.h"
#include "TError.h"
#include <iostream>
#include <stdexcept>

using namespace std;

ClassImp(TreeSearch::PatternTree)

namespace TreeSearch {

//_____________________________________________________________________________
PatternTree::PatternTree( const TreeParam_t& param, UInt_t nPatterns,
			  UInt_t nLinks )
try
  : fParameters(param), fParamOK(false), fNpat(0), fNlnk(0), fNbit(0)
{
  // Constructor. 

  if( fParameters.Normalize() != 0 )
    return;

  fPatterns.resize( nPatterns );
  fLinks.resize( nLinks );
  fBits.resize( nPatterns * fParameters.zpos().size() );

  fParamOK = true;
}
catch ( bad_alloc ) {
  ::Error( "PatternTree::PatternTree", "Out of memory trying to create "
	   "%u patterns, %u links. Tree not created.", nPatterns, nLinks );
  throw;
}

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

}

//_____________________________________________________________________________
PatternTree* PatternTree::Read( const char* filename, const TreeParam_t& tp )
{
  // Read tree from file

  try {

    // TODO: implement
  }
  catch ( bad_alloc ) {
    ::Error( "PatternTree::Read", "Out of memory trying to read "
	     "%u patterns, %u links", 0,0 );
    // TODO: clean up
  }

  return 0;
}


//_____________________________________________________________________________
Int_t TreeParam_t::Normalize()
{
  // Test, then normalize parameter values to width = 1 and z_max = 1.
  // Returns 0 on success, != 0 on error. On success only, the input data
  // are irreversibly modified: zpos.front() and zpos.back() will be 0 and 1,
  // respectively, and maxslope is scaled to the normalized aspect ratio.
  // width is not changed

  static const char* const here = "TreeParam_t::Normalize";

  if( fNormalized )  return 0;

  if( fMaxdepth >= 16 ) {
    ::Error( here, "Illegal maxdepth = %u. Must be < 16", fMaxdepth );
    return -1;
  }
  if( fWidth < 1e-2 ) {
    ::Error( here, "Illegal detector width %lf. Must be >= 0.01.", 
	     fWidth );
    return -2;
  }
  if( fZpos.size() < 3 || fZpos.size() > 16 ) {
    ::Error( here, "Illegal number of planes = %u. Must be between 3-16.",
	     fZpos.size() );
    return -3;
  }
  if( fMaxslope < 0.0 )
    fMaxslope = -fMaxslope;

  // Check fZpos array for sorting and minimum spacing
  for( vector<Double_t>::size_type i = 1; i < fZpos.size(); ++i ) {
    if( fZpos[i] < fZpos[i-1] + 1e-3 ) {
      ::Error( here, "Array of z-positions not sorted or planes not "
	       "spaced by at least 0.001 at index = %u.", i );
      return -4;
    }
  }

  // Normalize the z-positions to the interval [0,1]
  Double_t zsize = fZpos.back() - fZpos.front();
  for( vector<Double_t>::size_type i = 1; i+1 < fZpos.size(); ++i ) {
    fZpos[i] -= fZpos.front();
    fZpos[i] /= zsize;
  }
  fZpos.back()  = 1.0;
  fZpos.front() = 0.0;

  // Scale maxslope to the new aspect ratio
  fMaxslope *= zsize / fWidth;

  // NB: the width is not changed because we need it later
  fNormalized = true;

  return 0;
}

//_____________________________________________________________________________
void PatternTree::Print( Option_t* opt, ostream& os )
{
  // Print information about the tree, depending on option

  TreeWalk walk( GetNlevels() );
  // Print ASCII pictures of ALL actual patterns in the tree ("P") or
  // dump n-tuples of all actual patterns, one per line ("L")
  if( *opt == 'P' or *opt == 'L' ) {
    PrintPattern print(os, (*opt == 'L'));
    walk( GetRoot(), print );
    return;
  }

  // Count all actual patterns
  if( *opt == 'C' ) {
    CountPattern count;
    walk( GetRoot(), count );
    os << "Total pattern count = " << count.GetCount() << endl;
    return;
  }

  // Basic info
//   os << "tree: nlevels = " << fNlevels
//      << ", nplanes = " << fNplanes
//      << ", zpos = ";
//   for( UInt_t i=0; i<fZ.size(); i++ ) {
//     os << fZ[i];
//     if( i+1 != fZ.size() )
//       os << ",";
//   }
//   os << endl;

//   os << "patterns = " << fStats.nPatterns
//      << ", links = "   << fStats.nLinks
//      << ", bytes = " << fStats.nBytes
//      << endl;
//   os << "maxlinklen = " << fStats.MaxChildListLength
//      << ", hashsize = " << fHashTable.size()
//      << ", hashbytes = " << fStats.nHashBytes
//      << endl;
//   os << "time = " << fStats.BuildTime << " s" << endl;
}

//_____________________________________________________________________________
Int_t PatternTree::Write( const char* filename )
{
  // Write tree to binary file

  // TODO: write header

  size_t index_size = sizeof(Int_t);
  vpsz_t npatt = fPatterns.size();
  if( npatt < (1U<<8) )
    index_size = 1;
  else if( npatt < (1U<<16) )
    index_size = 2;
  WritePattern write(filename,index_size);
  TreeWalk walk( GetNlevels() );
  Int_t ret = walk( GetRoot(), write );
  if( ret != kError )
    ret = 0;
  return ret;
}

//_____________________________________________________________________________
void 
PatternTree::CopyPattern::AddChild( Pattern* node, Pattern* child, Int_t type )
{
  // Add child to node's child pattern list

  Link* ln = node->GetChild();
  while( ln ) {
    if( !ln->GetPattern() ) {
      SetLinkPattern( ln, child );
      SetLinkType( ln, type );
      break;
    }
    assert( ln->GetPattern() != child or ln->Type() != type );
    ln = ln->Next();
    assert(ln);  // An empty slot must exist somewhere in the list
  }
}

//_____________________________________________________________________________
NodeVisitor::ETreeOp
PatternTree::CopyPattern::operator() ( const NodeDescriptor& nd )
try {
  // Add pattern to the PatternTree fTree

  map<Pattern*,Int_t>::iterator idx;
  Pattern* copied_parent = 0;
  if( nd.parent ) {
    idx = fMap.find(nd.parent);
    assert( idx != fMap.end() );
    copied_parent = &(fTree->fPatterns.at( idx->second ));
  }
  Pattern* node = nd.link->GetPattern();
  idx = fMap.find(node);
  if( idx == fMap.end() ) {
    // New pattern: add pattern to pattern and bits arrays, and add its 
    // child links to links array
    map< Pattern*,Int_t>::size_type np = fMap.size();
    fMap[node] = np;
    assert( fTree->fNpat == np );
    Pattern* cur_pat = &(fTree->fPatterns.at(fTree->fNpat));
    // Copy the pattern to the array element via its assignment operator,
    // which sets the fChild pointer to zero and copies the bits
    *cur_pat = *node;
    // Per 2003 C++ Standard TC, std::vector is guaranteed to store its 
    // elements in contiguous memory, so this is safe:
    UShort_t* bitloc = &(fTree->fBits.at(fTree->fNbit));
    // Tell the pattern to store its bits at address bitloc. This copies the
    // bits into the fTree->fBits vector.
    cur_pat->SetBitloc( bitloc );
    // Link this pattern to its parent
    if( copied_parent ) {
      AddChild( copied_parent, cur_pat, nd.link->Type() );
    } else {
      // If there is no parent, this had better be the root node
      assert( fTree->fNlnk == 0 );
      fTree->fLinks.at(fTree->fNlnk++) = Link(cur_pat, 0, nd.link->Type());
    }
    // Create the child node links, but with empty pattern pointers
    Int_t nchild = node->GetNchildren();
    // Set the child pointer of the copied pattern to the first child node
    if( nchild > 0 ) {
      PatternTree::vlsz_t lpos = fTree->fNlnk;
      SetPatternChild( cur_pat, &(fTree->fLinks.at(lpos)) );
      // Link the child node list (not really needed, but we don't want the
      // fNext pointers to dangle)
      for( Int_t i = nchild-2; i >= 0; --i )
	SetLinkNext( &(fTree->fLinks.at(lpos+i)), 
		     &(fTree->fLinks.at(lpos+i+1)) );
    }
    // Update cursors
    fTree->fNpat++;
    fTree->fNlnk += nchild;
    fTree->fNbit += cur_pat->GetNbits();
    // Proceed with this pattern's child nodes
    return kRecurseUncond;
  } 
  else {
    // Existing pattern: add link to the parent pattern's child node list,
    // pointing to the referenced pattern
    Pattern* ref_node = &(fTree->fPatterns.at( idx->second ));
    AddChild( copied_parent, ref_node, nd.link->Type() );
    // Skip this pattern's child nodes since they are already in the tree
    return kSkipChildNodes;
  }
}
catch ( out_of_range ) {
  ::Error( "TreeSearch::CopyPattern", "Array index out of range at %u %u %u "
	   "(internal logic error). Tree not copied. Call expert.",
	   fTree->fNpat, fTree->fNlnk, fTree->fNbit );
  return kError;
}

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

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