int PHG4HoughTransformTPC::InitializeGeometry(PHCompositeNode *topNode) {

  //---------------------------------------------------------
  // Grab Run-Dependent Detector Geometry and Configure Hough
  //---------------------------------------------------------

  bool default_geo = false;
  
  PHG4CylinderCellGeomContainer* cellgeos = findNode::getClass<PHG4CylinderCellGeomContainer>(topNode,"CYLINDERCELLGEOM_SVTX");
  PHG4CylinderGeomContainer* laddergeos = findNode::getClass<PHG4CylinderGeomContainer>(topNode,"CYLINDERGEOM_SILICON_TRACKER");
  //PHG4CylinderCellContainer* cells = findNode::getClass<PHG4CylinderCellContainer>(topNode,"G4CELL_SVTX");
  
  if (cellgeos||laddergeos) {
    unsigned int ncelllayers = 0;
    if (cellgeos) ncelllayers += cellgeos->get_NLayers();
    unsigned int nladderlayers = 0;
    if (laddergeos) nladderlayers += laddergeos->get_NLayers();
    _nlayers = ncelllayers + nladderlayers;
    default_geo = false;
  } else {
    cerr << PHWHERE
	 << "Neither CYLINDERCELLGEOM_SVTX nor CYLINDERGEOM_SILICON_TRACKER available, reverting to a default geometry"
	 << std::endl;    
    _nlayers = 6;
    default_geo = true;
  }

  //=================================================//                                                                                                      
  //  Initializing HelixHough objects                //                                                                                                      
  //=================================================//                                                                                            

  _radii.assign(_nlayers, 0.0);
  _smear_xy_layer.assign(_nlayers, 0.0);
  _smear_z_layer.assign(_nlayers, 0.0);
  float sqrt_12 = sqrt(12.);
	
  if (default_geo) {

    // default geometry
    _radii[0] = 2.5;
    _radii[1] = 5.0;
    _radii[2] = 10.0;
    _radii[3] = 14.0;
    _radii[4] = 40.0;
    _radii[5] = 60.0;
    
    _smear_xy_layer[0] = (50.0e-4/sqrt_12);
    _smear_z_layer[0] = (425.0e-4/sqrt_12);
    _smear_xy_layer[1] = (50.0e-4/sqrt_12);
    _smear_z_layer[1] = (425.0e-4/sqrt_12);
    _smear_xy_layer[2] = (80.0e-4/sqrt_12);
    _smear_z_layer[2] = (1000.0e-4/sqrt_12);
    _smear_xy_layer[3] = (80.0e-4/sqrt_12);
    _smear_z_layer[3] = (1000.0e-4/sqrt_12);
    
    for(int il=4; il<_nlayers; ++il) {
      _smear_xy_layer[il] = (80.0e-4/sqrt_12);
      _smear_z_layer[il] = (30000.0e-4/sqrt_12);
    }

    _layer_ilayer_map.clear();
    for (int ilayer = 0; ilayer < _nlayers; ++ilayer) {
      _layer_ilayer_map.insert(make_pair(ilayer,ilayer));
    }
    
  } else {

    // Since the G4 layers don't necessarily correspond to the
    // silicon layers, and don't necessarily start from zero (argh),
    // we create our own layers numbers that are consecutive
    // starting from zero.

    // Now that we have two kinds of layers, I won't know in principle
    // which type is in what order, so I figure that out now...
    
    map<float,int> radius_layer_map;

    if (cellgeos) {
      PHG4CylinderCellGeomContainer::ConstRange layerrange = cellgeos->get_begin_end();
      for(PHG4CylinderCellGeomContainer::ConstIterator layeriter = layerrange.first;
	  layeriter != layerrange.second;
	  ++layeriter) {
	radius_layer_map.insert( make_pair(layeriter->second->get_radius(),
					   layeriter->second->get_layer()) );
      }
    }

    if (laddergeos) {
      PHG4CylinderGeomContainer::ConstRange layerrange = laddergeos->get_begin_end();
      for(PHG4CylinderGeomContainer::ConstIterator layeriter = layerrange.first;
	  layeriter != layerrange.second;
	  ++layeriter) {
	radius_layer_map.insert( make_pair(layeriter->second->get_radius(),
					   layeriter->second->get_layer()) );
      }
    }

    // now that the layer ids are sorted by radius, I can create a storage
    // index, ilayer, that is 0..N-1 and sorted by radius
    
    int ilayer = 0;
    for(map<float,int>::iterator iter = radius_layer_map.begin();
	iter != radius_layer_map.end();
	++iter) {
      _layer_ilayer_map.insert( make_pair(iter->second,ilayer) );
      ++ilayer;
    }   

    // now we extract the information from the cellgeos first
    if (cellgeos) {    
      PHG4CylinderCellGeomContainer::ConstRange begin_end = cellgeos->get_begin_end();
      PHG4CylinderCellGeomContainer::ConstIterator miter = begin_end.first;
      for( ; miter != begin_end.second; miter++) {
	PHG4CylinderCellGeom *cellgeo = miter->second;
      
	if (verbosity > 1) cellgeo->identify();

	_radii[_layer_ilayer_map[cellgeo->get_layer()]] = cellgeo->get_radius();      
	_smear_xy_layer[_layer_ilayer_map[cellgeo->get_layer()]] = cellgeo->get_radius()*cellgeo->get_phistep();
	_smear_z_layer[_layer_ilayer_map[cellgeo->get_layer()]] = cellgeo->get_zstep();     
      }
    }

    if (laddergeos) {    
      PHG4CylinderGeomContainer::ConstRange begin_end = laddergeos->get_begin_end();
      PHG4CylinderGeomContainer::ConstIterator miter = begin_end.first;
      for( ; miter != begin_end.second; miter++) {
	PHG4CylinderGeom *geo = miter->second;
	
	if (verbosity > 1) geo->identify();
	
	_radii[_layer_ilayer_map[geo->get_layer()]] = geo->get_radius();      
	_smear_xy_layer[_layer_ilayer_map[geo->get_layer()]] = geo->get_strip_y_spacing();
	_smear_z_layer[_layer_ilayer_map[geo->get_layer()]] = geo->get_strip_z_spacing();     
      }
    }
  }  

  // set material on each layer
  
  _material.assign(_radii.size(), 0.03);

  map<int, float>::iterator mat_it;
  for (map<int, float>::iterator iter = _user_material.begin();
       iter != _user_material.end();
       ++iter) {
    _material[_layer_ilayer_map[iter->first]] = iter->second;
  }

  float kappa_max = ptToKappa(_min_pT);

  HelixRange top_range( 0.0, 2.*M_PI,
		       -0.2, 0.2,
			0.0, kappa_max,
		       -0.9, 0.9,
		       -1.0*_dcaz_cut, 1.0*_dcaz_cut);
  if (!_use_vertex) {
    top_range.min_z0 = -10.;
    top_range.max_z0 = 10.;
  }
  
  vector<unsigned int> onezoom(5,0);
  vector<vector<unsigned int> > zoomprofile;
  zoomprofile.assign(3,onezoom);
  zoomprofile[0][0] = 16;
  zoomprofile[0][1] = 1;
  zoomprofile[0][2] = 4;
  zoomprofile[0][3] = 8;
  zoomprofile[0][4] = 1;
  
  zoomprofile[1][0] = 16;
  zoomprofile[1][1] = 1;
  zoomprofile[1][2] = 4;
  zoomprofile[1][3] = 4;
  zoomprofile[1][4] = 1;
  
  zoomprofile[2][0] = 4;
  zoomprofile[2][1] = 2;
  zoomprofile[2][2] = 2;
  zoomprofile[2][3] = 2;
  zoomprofile[2][4] = 2;
  
  // for (unsigned int i = 3; i <= 4; ++i) {
  //   zoomprofile[i][0] = 4;
  //   zoomprofile[i][1] = 2;
  //   zoomprofile[i][2] = 2;
  //   zoomprofile[i][3] = 3;
  //   zoomprofile[i][4] = 2;
  // }
    
  _tracker = new sPHENIXTracker(zoomprofile, 1, top_range, _material, _radii, _magField);
  _tracker->setIterateClustering(true);
  _tracker->setNLayers(_seed_layers);
  _tracker->requireLayers(_req_seed);
  _max_hits_init = _seed_layers*4;
  if(_seed_layers >= 10){_max_hits_init = _seed_layers*2;}
  _min_hits_init = _req_seed;
  if(_seed_layers < 10){ _tracker->setClusterStartBin(1); }
  else{ _tracker->setClusterStartBin(10); }
  _tracker->setRejectGhosts(_reject_ghosts);
  _tracker->setFastChi2Cut(_chi2_cut_fast_par0,
			   _chi2_cut_fast_par1,
			   _chi2_cut_fast_max);
  _tracker->setChi2Cut(_chi2_cut_full);
  _tracker->setChi2RemovalCut(_chi2_cut_full*0.5);
  _tracker->setCellularAutomatonChi2Cut(_ca_chi2_cut);
  _tracker->setPrintTimings(false);
  if(verbosity > 3){_tracker->setPrintTimings(true);}
  _tracker->setVerbosity(verbosity);
  _tracker->setCutOnDca(_cut_on_dca);
  _tracker->setDcaCut(_dca_cut);
  _tracker->setSmoothBack(false);
  _tracker->setBinScale(_bin_scale);
  _tracker->setZBinScale(_z_bin_scale);
  _tracker->setRemoveHits(_remove_hits);
  _tracker->setSeparateByHelicity(true);
  _tracker->setMaxHitsPairs(0);
  _tracker->setCosAngleCut(_cos_angle_cut);
  
  
  vector<vector<unsigned int> > zoomprofile_init;
  zoomprofile_init.assign(4,onezoom);
  for(unsigned int i=0;i<=1;++i)
  {
    zoomprofile_init[i][0] = 8;
    zoomprofile_init[i][1] = 1;
    zoomprofile_init[i][2] = 3;
    zoomprofile_init[i][3] = 4;
    zoomprofile_init[i][4] = 4;
  }
  for(unsigned int i=2;i<=3;++i)
  {
    zoomprofile_init[i][0] = 8;
    zoomprofile_init[i][1] = 1;
    zoomprofile_init[i][2] = 2;
    zoomprofile_init[i][3] = 2;
    zoomprofile_init[i][4] = 2;
  }
  vector<HelixRange> top_range_init;
  unsigned int nphi = 1;
  unsigned int nz0 = 5;
  double phimin = 0.;
  double phi_step = 2.0*M_PI/((double)nphi);
  float kappa_max_init = ptToKappa(_min_pT_init);
  for(unsigned int i=0;i<nphi;++i)
  {
    double z0min = -10.;
    double z0_step = 20./((double)nz0);
    for(unsigned int j=0;j<nz0;++j)
    {
      top_range_init.push_back(HelixRange(phimin, phimin+phi_step,   -0.2, 0.2,   0.0, kappa_max_init,   -0.9, 0.9,   z0min, z0min+z0_step));
      _tracker_vertex.push_back( new sPHENIXTracker(zoomprofile_init, 1, top_range_init.back(), _material, _radii, _magField) );
      if(verbosity > 3){(_tracker_vertex.back())->setPrintTimings(true);}
      (_tracker_vertex.back())->setVerbosity(verbosity);
      (_tracker_vertex.back())->setNLayers(_seed_layers);
      (_tracker_vertex.back())->requireLayers(_req_seed);
      (_tracker_vertex.back())->setClusterStartBin(1);
      (_tracker_vertex.back())->setRejectGhosts(true);
      (_tracker_vertex.back())->setFastChi2Cut(_chi2_cut_fast_par0,
					       _chi2_cut_fast_par1,
					       _chi2_cut_fast_max);
      (_tracker_vertex.back())->setChi2Cut(_chi2_cut_init);
      (_tracker_vertex.back())->setChi2RemovalCut(_chi2_cut_init*0.5);
      (_tracker_vertex.back())->setCellularAutomatonChi2Cut(_ca_chi2_cut);
      (_tracker_vertex.back())->setCutOnDca(false);
      (_tracker_vertex.back())->setSmoothBack(true);
      (_tracker_vertex.back())->setBinScale(_bin_scale);
      (_tracker_vertex.back())->setZBinScale(_z_bin_scale);
      (_tracker_vertex.back())->setRemoveHits(false);
      (_tracker_vertex.back())->setSeparateByHelicity(true);
      (_tracker_vertex.back())->setMaxHitsPairs(0);
      (_tracker_vertex.back())->setCosAngleCut(_cos_angle_cut);
      z0min += z0_step;
    }
    phimin += phi_step;
  }
  
  for(unsigned int ilayer = 0; ilayer < _fit_error_scale.size(); ++ilayer) {
    float scale1 = _fit_error_scale[ilayer];
    float scale2 = _vote_error_scale[ilayer];
    float scale = scale1/scale2;
    _tracker->setHitErrorScale(ilayer, scale);
    for(unsigned int j = 0; j < _tracker_vertex.size(); ++j) {
      _tracker_vertex[j]->setHitErrorScale(ilayer, scale);
    }
  }
  
  return Fun4AllReturnCodes::EVENT_OK;
}
int PHG4HoughTransform::InitializeGeometry(PHCompositeNode *topNode) {

  //---------------------------------------------------------
  // Grab Run-Dependent Detector Geometry and Configure Hough
  //---------------------------------------------------------

  PHG4CylinderCellGeomContainer* cellgeos =
      findNode::getClass<PHG4CylinderCellGeomContainer>(
          topNode, "CYLINDERCELLGEOM_SVTX");
  PHG4CylinderGeomContainer* laddergeos =
      findNode::getClass<PHG4CylinderGeomContainer>(
          topNode, "CYLINDERGEOM_SILICON_TRACKER");
  PHG4CylinderGeomContainer* mapsladdergeos =
      findNode::getClass<PHG4CylinderGeomContainer>(
          topNode, "CYLINDERGEOM_MAPS");

  if (cellgeos || laddergeos || mapsladdergeos) {
    unsigned int ncelllayers = 0;
    if (cellgeos) ncelllayers += cellgeos->get_NLayers();
    unsigned int nladderlayers = 0;
    if (laddergeos) nladderlayers += laddergeos->get_NLayers();
    unsigned int nmapsladderlayers = 0;
    if (mapsladdergeos) nmapsladderlayers += mapsladdergeos->get_NLayers();
    _nlayers = ncelllayers + nladderlayers + nmapsladderlayers;
  } else {
    cerr << PHWHERE
         << "None of  CYLINDERCELLGEOM_SVTX or CYLINDERGEOM_SILICON_TRACKER or CYLINDERGEOM_MAPS"
            "available, bail"
         << std::endl;
    return Fun4AllReturnCodes::ABORTRUN;
  }

  //=================================================//
  //  Initializing HelixHough objects                //
  //=================================================//
  	
  // Since the G4 layers don't necessarily correspond to the
  // silicon layers, and don't necessarily start from zero (argh),
  // we create our own layers numbers that are consecutive
  // starting from zero.

  // Now that we have two kinds of layers, I won't know in principle
  // which type is in what order, so I figure that out now...

  _radii.assign(_nlayers, 0.0);    
  map<float,int> radius_layer_map;

  if (cellgeos) {
    PHG4CylinderCellGeomContainer::ConstRange layerrange = cellgeos->get_begin_end();
    for(PHG4CylinderCellGeomContainer::ConstIterator layeriter = layerrange.first;
	layeriter != layerrange.second;
	++layeriter) {
      radius_layer_map.insert( make_pair(layeriter->second->get_radius(),
					 layeriter->second->get_layer()) );
    }
  }

  if (laddergeos) {
    PHG4CylinderGeomContainer::ConstRange layerrange = laddergeos->get_begin_end();
    for(PHG4CylinderGeomContainer::ConstIterator layeriter = layerrange.first;
	layeriter != layerrange.second;
	++layeriter) {
      radius_layer_map.insert( make_pair(layeriter->second->get_radius(),
					 layeriter->second->get_layer()) );
    }
  }

  if (mapsladdergeos) {
    PHG4CylinderGeomContainer::ConstRange layerrange = mapsladdergeos->get_begin_end();
    for(PHG4CylinderGeomContainer::ConstIterator layeriter = layerrange.first;
	layeriter != layerrange.second;
	++layeriter) {
      radius_layer_map.insert( make_pair(layeriter->second->get_radius(),
					 layeriter->second->get_layer()) );
    }
  }

  // now that the layer ids are sorted by radius, I can create a storage
  // index, ilayer, that is 0..N-1 and sorted by radius
  
  int ilayer = 0;
  for(map<float,int>::iterator iter = radius_layer_map.begin();
      iter != radius_layer_map.end();
      ++iter) {
    _layer_ilayer_map.insert( make_pair(iter->second,ilayer) );
    ++ilayer;
  }   

  // now we extract the information from the cellgeos first
  if (cellgeos) {    
    PHG4CylinderCellGeomContainer::ConstRange begin_end = cellgeos->get_begin_end();
    PHG4CylinderCellGeomContainer::ConstIterator miter = begin_end.first;
    for( ; miter != begin_end.second; miter++) {
      PHG4CylinderCellGeom *cellgeo = miter->second;
      
      if (verbosity > 1) cellgeo->identify();
      
      _radii[_layer_ilayer_map[cellgeo->get_layer()]] = cellgeo->get_radius();      
    }
  }

  if (laddergeos) {    
    PHG4CylinderGeomContainer::ConstRange begin_end = laddergeos->get_begin_end();
    PHG4CylinderGeomContainer::ConstIterator miter = begin_end.first;
    for( ; miter != begin_end.second; miter++) {
      PHG4CylinderGeom *geo = miter->second;
      
      if (verbosity > 1) geo->identify();
      
      _radii[_layer_ilayer_map[geo->get_layer()]] = geo->get_radius();      
    }
  }

  if (mapsladdergeos) {    
    PHG4CylinderGeomContainer::ConstRange begin_end = mapsladdergeos->get_begin_end();
    PHG4CylinderGeomContainer::ConstIterator miter = begin_end.first;
    for( ; miter != begin_end.second; miter++) {
      PHG4CylinderGeom *geo = miter->second;
      
      if (verbosity > 1) geo->identify();
      
      _radii[_layer_ilayer_map[geo->get_layer()]] = geo->get_radius();      
    }
  }

  // set material on each layer
  
  _material.assign(_radii.size(), 0.03);

  map<int, float>::iterator mat_it;
  for (map<int, float>::iterator iter = _user_material.begin();
       iter != _user_material.end();
       ++iter) {
    _material[_layer_ilayer_map[iter->first]] = iter->second;
  }

  // initialize the pattern recogition tools

  setup_tracker_object();
  setup_initial_tracker_object();
  setup_seed_tracker_objects();
  
  return Fun4AllReturnCodes::EVENT_OK;
}