int PHG4HoughTransformTPC::process_event(PHCompositeNode *topNode)
{
  _timer.get()->restart();
  if(_write_reco_tree==true){ _recoevent->tracks.clear();}

  if(verbosity > 0) cout << "PHG4HoughTransformTPC::process_event -- entered" << endl;

  // moving clearing to the beginning of event or we will have
  // return bugs from early exits!
  _clusters_init.clear();
  _clusters.clear();
  _tracks.clear();
  
  //---------------------------------
  // Get Objects off of the Node Tree
  //---------------------------------
  
  GetNodes(topNode);
  
  // Translate into Helix_Hough objects
  //-----------------------------------
  //wrap_clusters_timer.get()->restart();

  for (SvtxClusterMap::Iter iter = _g4clusters->begin();
       iter != _g4clusters->end();
       ++iter) {
    SvtxCluster* cluster = iter->second;

    //cluster->identify();
    
    float phi = atan2(cluster->get_position(1),cluster->get_position(0));
    unsigned int ilayer = _layer_ilayer_map[cluster->get_layer()];
    
    float xy_error=0.;float z_error=0.;
    if (_use_cell_size) {
      xy_error = _smear_xy_layer[ilayer] * _vote_error_scale[ilayer];
      z_error  = _smear_z_layer[ilayer] * _vote_error_scale[ilayer];
      
    }
    else {
      if( cluster->get_phi_size() <= _max_cluster_error*_smear_xy_layer[ilayer] ){xy_error = cluster->get_phi_size() * _vote_error_scale[ilayer];}
      else{xy_error = _max_cluster_error*_smear_xy_layer[ilayer] * _vote_error_scale[ilayer];}
      if(cluster->get_z_size() <= _max_cluster_error*_smear_z_layer[ilayer]){z_error  = cluster->get_z_size() * _vote_error_scale[ilayer];}
      else{z_error  = _max_cluster_error*_smear_z_layer[ilayer] * _vote_error_scale[ilayer];}
    }

    vector<SimpleHit3D>* which_vec = &_clusters;
    if (ilayer<_seed_layers) {which_vec=&_clusters_init;}

    //SimpleHit3D(float xx, float dxx, float yy, float dyy, float zz, float dzz, unsigned int ind, int lyr=-1)
    SimpleHit3D hit3d(cluster->get_x(),fabs(xy_error*sin(phi)),
		      cluster->get_y(),fabs(xy_error*cos(phi)),
		      cluster->get_z(),z_error,
		      cluster->get_id(),ilayer);

    // copy covariance over
    for (int i=0; i<3; ++i) {
      for (int j=i; j<3; ++j) {
	hit3d.set_error(i,j,cluster->get_error(i,j));
      }
    }

    which_vec->push_back(hit3d);
  }

  if (verbosity > 20) {
    cout << "-------------------------------------------------------------------" << endl;
    cout << "PHG4HoughTransformTPC::process_event has the following input clusters:" << endl;

    if (!_clusters_init.empty()) {
      for (unsigned int i = 0; i < _clusters_init.size(); ++i) {
	cout << "n init clusters = "<<_clusters_init.size() << endl;
	_clusters_init[i].print();
      }
    } else {
      for (unsigned int i = 0; i < _clusters.size(); ++i) {
	cout << "n clusters = "<<_clusters.size() << endl;
	_clusters[i].print();
      }
    }
    
    cout << "-------------------------------------------------------------------" << endl;
  }

  cout<<"_clusters_init.size() = "<<_clusters_init.size()<<endl;
  
  //------------------------------------
  // Perform the initial zvertex finding
  //------------------------------------

  if(verbosity > 0) cout << "PHG4HoughTransformTPC::process_event -- initial vertex finding..." << endl;

  // Grab some initial tracks for initial z-vertex finding
  _tracks.clear();

  _vertex.clear();
  _vertex.push_back(0.0); // x guess
  _vertex.push_back(0.0); // y guess
  _vertex.push_back(0.0); // z guess

  if(_use_vertex) {
    
    // find maxtracks tracks
    unsigned int maxtracks = 100;
    // _tracker->setRemoveHits(false);
    _tracker->findHelices(_clusters_init, _req_seed, _max_hits_init, _tracks, maxtracks);
    // _tracker->setRemoveHits(_remove_hits);

    cout<<"found "<<_tracks.size()<<" tracks"<<endl;
    
    if(_tracks.size() == 0){return Fun4AllReturnCodes::EVENT_OK;}
    else if(_tracks.size() == 1)
    {
      _vertex[0] = cos(_tracks[0].phi) * _tracks[0].d;
      _vertex[1] = sin(_tracks[0].phi) * _tracks[0].d;
      _vertex[2] = _tracks[0].z0;
    }
    else
    {
      vector<vector<double> > pTmap;
      for(unsigned int i=0;i<_tracks.size();++i)
      {
        if(_tracks[i].kappa == 0.0){continue;}
        double pT = kappaToPt(_tracks[i].kappa);
        pTmap.push_back(vector<double>());
        pTmap.back().push_back(pT);
        pTmap.back().push_back((double)i);
      }
      sort(pTmap.begin(), pTmap.end());
      vector<SimpleTrack3D> vtxtracks;
      unsigned int maxvtxtracks=100;
      if(_tracks.size() < maxvtxtracks)
      {
        vtxtracks = _tracks;
      }
      else
      {
        for(unsigned int i=0;i<maxvtxtracks;++i)
        {
          vtxtracks.push_back(_tracks[ (int)(pTmap[pTmap.size()-1-i][1]) ]);
        }
      }
      
      
      vector<double> zvertices(3,0.);
      vector<float> temp_vertex(3,0.);
      vector<unsigned int> vtracks(3,0);
      for(unsigned int iter = 0;iter < 3; ++iter)
      {
        temp_vertex[2] = 0.;
        
        TH1D z0_hist("z0_hist","z0_hist", 20, -10., 10.);
        for(unsigned int i=0;i<vtxtracks.size();++i)
        {
          z0_hist.Fill(vtxtracks[i].z0);
        }
        temp_vertex[2] = z0_hist.GetBinCenter( z0_hist.GetMaximumBin() );
        
        _vertexFinder.findVertex(vtxtracks, temp_vertex, 3., true);
        _vertexFinder.findVertex(vtxtracks, temp_vertex, 0.1, true);
        _vertexFinder.findVertex(vtxtracks, temp_vertex, 0.02, false);
        
        
        vector<SimpleTrack3D> ttracks;
        for(unsigned int t=0;t<vtxtracks.size();++t)
        {
          if( fabs(vtxtracks[t].z0 - temp_vertex[2]) < 0.1 ){vtracks[iter] += 1;}
          else{ttracks.push_back(vtxtracks[t]);}
        }
        vtxtracks = ttracks;
        zvertices[iter] = temp_vertex[2];
      }
      _vertex[2] = zvertices[0];
      unsigned int zbest = 0;
      for(unsigned int iter = 1;iter < 3; ++iter)
      {
        if(vtracks[iter] > vtracks[zbest])
        {
          _vertex[2] = zvertices[iter];
          zbest = iter;
        }
      }
    }
    
    
    
    
    
    
    if(verbosity > 0) cout << "PHG4HoughTransformTPC::process_event -- found initial vertex : " << _vertex[0] << " " << _vertex[1] << " " << _vertex[2] << endl;
    
    _tracks.clear();
    
    // shift the vertex to the origin
    for(unsigned int ht=0;ht<_clusters_init.size();++ht)
    {
      _clusters_init[ht].x -= _vertex[0];
      _clusters_init[ht].y -= _vertex[1];
      _clusters_init[ht].z -= _vertex[2];
    }
    for(unsigned int ht=0;ht<_clusters.size();++ht)
    {
      _clusters[ht].x -= _vertex[0];
      _clusters[ht].y -= _vertex[1];
      _clusters[ht].z -= _vertex[2];
    }
    
    

    
  }  // if(_use_vertex)
  
  //----------------------------------
  // Preform the track finding
  //----------------------------------
  _tracker->clear();
  _tracks.clear();
  _timer_initial_hough.get()->restart();
  _tracker->findHelices(_clusters_init, _min_hits_init, _max_hits_init, _tracks);

  _timer_initial_hough.get()->stop();
  
  

  if(verbosity > 0)
  {
    cout << "PHG4HoughTransformTPC::process_event -- full track finding pass found: " << _tracks.size() << " tracks" << endl;
  }    
   
  //----------------------------
  // Re-center event on detector
  //----------------------------

  if(verbosity > 0) cout << "PHG4HoughTransformTPC::process_event -- recentering event on detector..." << endl;
  vector<double> chi_squareds;
  for(unsigned int tt=0;tt<_tracks.size();tt++)
  {
    // move the hits in the track back to their original position                
    for(unsigned int hh=0;hh<_tracks[tt].hits.size();hh++)
    {
      _tracks[tt].hits[hh].x = _tracks[tt].hits[hh].x + _vertex[0];
      _tracks[tt].hits[hh].y = _tracks[tt].hits[hh].y + _vertex[1];
      _tracks[tt].hits[hh].z = _tracks[tt].hits[hh].z + _vertex[2];
      // _tracks[tt].z0 += _vertex[2];
    }
    chi_squareds.push_back(_tracker->getKalmanStates()[tt].chi2);}

  if(verbosity > 0)
  {
    cout << "PHG4HoughTransformTPC::process_event -- final track count: " << _tracks.size() << endl;
  }

  //---------------------------
  // Final vertex determination
  //---------------------------
  
  // final best guess of the primary vertex position here...
  if(verbosity > 0)
  {
    cout<< "PHG4HoughTransformTPC::process_event -- calculating final vertex" << endl;
  }
  
  // sort the tracks by pT
  vector<vector<double> > pTmap;
  for(unsigned int i=0;i<_tracks.size();++i)
  {
    double pT = kappaToPt(_tracks[i].kappa);
    pTmap.push_back(vector<double>());
    pTmap.back().push_back(pT);
    pTmap.back().push_back((double)i);
  }
  sort(pTmap.begin(), pTmap.end());
  vector<SimpleTrack3D> vtxtracks;
  vector<Matrix<float,5,5> > vtxcovariances;
  unsigned int maxvtxtracks=100;
  if(_tracks.size() < maxvtxtracks){vtxtracks = _tracks;}
  else
  {
    for(unsigned int i=0;i<maxvtxtracks;++i)
    {
      vtxtracks.push_back(_tracks[ (int)(pTmap[pTmap.size()-1-i][1]) ]);
      vtxcovariances.push_back( (_tracker->getKalmanStates())[ (int)(pTmap[pTmap.size()-1-i][1]) ].C );
    }
  }
  
  double vx = _vertex[0];
  double vy = _vertex[1];
  double vz = _vertex[2];
  
  _vertex[0] = 0.;
  _vertex[1] = 0.;
  _vertex[2] = 0.;
  
  _vertexFinder.findVertex(vtxtracks, vtxcovariances, _vertex, 0.3, false);
  _vertexFinder.findVertex(vtxtracks, vtxcovariances, _vertex, 0.1, false);
  _vertexFinder.findVertex(vtxtracks, vtxcovariances, _vertex, 0.02, false);
  _vertexFinder.findVertex(vtxtracks, vtxcovariances, _vertex, 0.005, false);
  
  _vertex[0] += vx;
  _vertex[1] += vy;
  _vertex[2] += vz;
  
  if(verbosity > 0)
  {
    cout << "PHG4HoughTransformTPC::process_event -- final vertex: " << _vertex[0] << " " << _vertex[1] << " " << _vertex[2] << endl;
  }

  //--------------------------------
  // Translate back into PHG4 objects
  //--------------------------------

  if(verbosity > 0)
  {
    cout << "PHG4HoughTransformTPC::process_event -- producing PHG4Track objects..." << endl;
  }

  SvtxVertex_v1 vertex;
  vertex.set_t0(0.0);
  for (int i=0;i<3;++i) vertex.set_position(i,_vertex[i]);
  vertex.set_chisq(0.0);
  vertex.set_ndof(0); 
  vertex.set_error(0,0,0.0);
  vertex.set_error(0,1,0.0);
  vertex.set_error(0,2,0.0);
  vertex.set_error(1,0,0.0);
  vertex.set_error(1,1,0.0);
  vertex.set_error(1,2,0.0);
  vertex.set_error(2,0,0.0);
  vertex.set_error(2,1,0.0);
  vertex.set_error(2,2,0.0);
  
  // copy out the reconstructed vertex position
  //_g4tracks->setVertex(_vertex[0],_vertex[1],_vertex[2]);
  //_g4tracks->setVertexError(0.0,0.0,0.0);
 
  // at this point we should already have an initial pt and pz guess...
  // need to translate this into the PHG4Track object...

  vector<SimpleHit3D> track_hits;
  int clusterID;
  int clusterLayer;
  float cluster_x;
  float cluster_y;
  float cluster_z;
  //  float dEdx1;
  //  float dEdx2;

  for(unsigned int itrack=0; itrack<_tracks.size();itrack++)
  {
    SvtxTrack_v1 track;
    track.set_id(itrack);
    track_hits.clear();
    track_hits = _tracks.at(itrack).hits;
    
    for(unsigned int ihit = 0; ihit<track_hits.size();ihit++)
    {
      //      dEdx1=0;
      //      dEdx2=0;
      if( (track_hits.at(ihit).index) >= _g4clusters->size()){continue;}
      SvtxCluster *cluster = _g4clusters->get(track_hits.at(ihit).index);
      clusterID = cluster->get_id();
      clusterLayer = cluster->get_layer();
      cluster_x = cluster->get_x();
      cluster_y = cluster->get_y();
      cluster_z = cluster->get_z();
      if( (clusterLayer < (int)_seed_layers) && (clusterLayer >= 0) )
      {
        track.insert_cluster(clusterID);
      }
    }
    float kappa = _tracks.at(itrack).kappa;
    float d = _tracks.at(itrack).d;
    float phi = _tracks.at(itrack).phi;

    float dzdl = _tracks.at(itrack).dzdl;
    float z0 = _tracks.at(itrack).z0;
    
    // track.set_helix_phi(phi);
    // track.set_helix_kappa(kappa);
    // track.set_helix_d(d);
    // track.set_helix_z0(z0);
    // track.set_helix_dzdl(dzdl);
    
    float pT = kappaToPt(kappa);

    float x_center = cos(phi)*(d+1/kappa); // x coordinate of circle center
    float y_center = sin(phi)*(d+1/kappa); // y    "      "     "      "

    // find helicity from cross product sign
    short int helicity;
    if((track_hits[0].x-x_center)*(track_hits[track_hits.size()-1].y-y_center) -
       (track_hits[0].y-y_center)*(track_hits[track_hits.size()-1].x-x_center) > 0)
    {
      helicity = 1;
    }
    else
    { 
      helicity = -1;
    }
    float pZ = 0;
    if(dzdl != 1)
    {
      pZ = pT * dzdl / sqrt(1.0 - dzdl*dzdl);
    }
    int ndf = 2*_tracks.at(itrack).hits.size() - 5;
    track.set_chisq(chi_squareds[itrack]);
    track.set_ndf(ndf);
    track.set_px( pT*cos(phi-helicity*M_PI/2) );
    track.set_py( pT*sin(phi-helicity*M_PI/2) );
    track.set_pz( pZ );

    track.set_dca2d( d );
    track.set_dca2d_error(sqrt(_tracker->getKalmanStates()[itrack].C(1,1)));  

    if(_write_reco_tree==true)
    {
      _recoevent->tracks.push_back( SimpleRecoTrack() );
      _recoevent->tracks.back().px = pT*cos(phi-helicity*M_PI/2);
      _recoevent->tracks.back().py = pT*sin(phi-helicity*M_PI/2);
      _recoevent->tracks.back().pz = pZ;
      _recoevent->tracks.back().d = d;
      _recoevent->tracks.back().z0 = z0;
      _recoevent->tracks.back().quality = chi_squareds[itrack]/((float)ndf);
      _recoevent->tracks.back().charge = (-1*helicity);
    }
    

    if(_magField > 0)
    {
      track.set_charge( helicity );
    }
    else
    {
      track.set_charge( -1.0*helicity );
    }

    Matrix<float,6,6> euclidean_cov = Matrix<float,6,6>::Zero(6,6);
    convertHelixCovarianceToEuclideanCovariance( _magField, phi, d, kappa, z0, dzdl, _tracker->getKalmanStates()[itrack].C, euclidean_cov );
    
    for(unsigned int row=0;row<6;++row)
    {
      for(unsigned int col=0;col<6;++col)
      {
	track.set_error(row,col,euclidean_cov(row,col));
      }
    }

    track.set_x( vertex.get_x() + d*cos(phi) );
    track.set_y( vertex.get_y() + d*sin(phi) );
    track.set_z( vertex.get_z() + z0 );
    
    _g4tracks->insert(&track);
    vertex.insert_track(track.get_id());

    if (verbosity > 5) {
      cout << "track " << itrack << " quality = "
           << track.get_quality() << endl;
      cout << "px = " << track.get_px()
           << " py = " << track.get_py()
           << " pz = " << track.get_pz() << endl;
    }
  } // track loop

  SvtxVertex *vtxptr = _g4vertexes->insert(&vertex);
  if (verbosity > 5) vtxptr->identify();
  
  if(verbosity > 0)
  {
    cout << "PHG4HoughTransformTPC::process_event -- leaving process_event" << endl;
  }

  if(_write_reco_tree==true){ _reco_tree->Fill(); }

  _timer.get()->stop();
  return Fun4AllReturnCodes::EVENT_OK;
}
Ejemplo n.º 2
0
void PHG4SvtxClusterizer::ClusterLadderCells(PHCompositeNode *topNode) {

  //----------
  // Get Nodes
  //----------

  // get the SVX geometry object
  PHG4CylinderGeomContainer* geom_container = findNode::getClass<PHG4CylinderGeomContainer>(topNode,"CYLINDERGEOM_SILICON_TRACKER");
  if (!geom_container) return;
  
  PHG4HitContainer* g4hits =  findNode::getClass<PHG4HitContainer>(topNode,"G4HIT_SILICON_TRACKER");
  if (!g4hits) return;
  
  PHG4CylinderCellContainer* cells =  findNode::getClass<PHG4CylinderCellContainer>(topNode,"G4CELL_SILICON_TRACKER");
  if (!cells) return; 
 
  //-----------
  // Clustering
  //-----------

  // sort hits layer by layer
  std::multimap<int,SvtxHit*> layer_hits_mmap;
  for (SvtxHitMap::Iter iter = _hits->begin();
       iter != _hits->end();
       ++iter) {
    SvtxHit* hit = &iter->second;
    layer_hits_mmap.insert(make_pair(hit->get_layer(),hit));
  }
  
  PHG4CylinderGeomContainer::ConstRange layerrange = geom_container->get_begin_end();
  for(PHG4CylinderGeomContainer::ConstIterator layeriter = layerrange.first;
      layeriter != layerrange.second;
      ++layeriter) {

    int layer = layeriter->second->get_layer();

    std::map<PHG4CylinderCell*,SvtxHit*> cell_hit_map;
    vector<PHG4CylinderCell*> cell_list;
    for (std::multimap<int,SvtxHit*>::iterator hiter = layer_hits_mmap.lower_bound(layer);
	 hiter != layer_hits_mmap.upper_bound(layer);
	 ++hiter) {
      SvtxHit* hit = hiter->second;
      PHG4CylinderCell* cell = cells->findCylinderCell(hit->get_cellid());
      cell_list.push_back(cell);
      cell_hit_map.insert(make_pair(cell,hit));
    }
    
    if (cell_list.size() == 0) continue; // if no cells, go to the next layer
    
    // i'm not sure this sorting is ever really used
    sort(cell_list.begin(), cell_list.end(), PHG4SvtxClusterizer::ladder_lessthan);

    typedef adjacency_list <vecS, vecS, undirectedS> Graph;
    typedef graph_traits<Graph>::vertex_descriptor Vertex;
    Graph G;

    for(unsigned int i=0; i<cell_list.size(); i++) {
      for(unsigned int j=i+1; j<cell_list.size(); j++) {
        if(ladder_are_adjacent(cell_list[i], cell_list[j]) )
          add_edge(i,j,G);
      }
      
      add_edge(i,i,G);
    }

    // Find the connections between the vertices of the graph (vertices are the rawhits, 
    // connections are made when they are adjacent to one another)
    vector<int> component(num_vertices(G));
    
    // this is the actual clustering, performed by boost
    connected_components(G, &component[0]); 

    // Loop over the components(hit cells) compiling a list of the
    // unique connected groups (ie. clusters).
    set<int> cluster_ids; // unique components
    multimap<int, PHG4CylinderCell*> clusters;
    for (unsigned int i=0; i<component.size(); i++) {
      cluster_ids.insert( component[i] );
      clusters.insert( make_pair(component[i], cell_list[i]) );
    }
    
    // 
    for (set<int>::iterator clusiter = cluster_ids.begin(); 
	 clusiter != cluster_ids.end(); 
	 clusiter++ ) {
      
      int clusid = *clusiter;
      pair<multimap<int, PHG4CylinderCell*>::iterator,
	   multimap<int, PHG4CylinderCell*>::iterator> clusrange = clusters.equal_range(clusid);
      
      multimap<int, PHG4CylinderCell*>::iterator mapiter = clusrange.first;
      
      int layer = mapiter->second->get_layer();
      PHG4CylinderGeom* geom = geom_container->GetLayerGeom(layer);
      
      SvtxCluster clus;
      clus.set_layer( layer );
      float clus_energy = 0.0;
      unsigned int clus_adc = 0;

      // determine the size of the cluster in phi and z
      // useful for track fitting the cluster

      set<int> phibins;
      set<int> zbins;
      for (mapiter = clusrange.first; mapiter != clusrange.second; mapiter++ ) {
	PHG4CylinderCell* cell = mapiter->second;     
	
	phibins.insert(cell->get_binphi());
	zbins.insert(cell->get_binz());
      }

      float thickness = geom->get_thickness();
      float pitch = geom->get_strip_y_spacing();
      float length = geom->get_strip_z_spacing();
      float phisize = phibins.size()*pitch;
      float zsize = zbins.size()*length;
      float tilt = geom->get_strip_tilt();

      // determine the cluster position...
      double xsum = 0.0;
      double ysum = 0.0;
      double zsum = 0.0;
      unsigned nhits = 0;

      int ladder_z_index = -1;
      int ladder_phi_index = -1;
      
      for(mapiter = clusrange.first; mapiter != clusrange.second; mapiter++ ) {
        PHG4CylinderCell* cell = mapiter->second;
	SvtxHit* hit = cell_hit_map[cell];
	
	clus.insert_hit(hit->get_id());
	
        clus_energy += hit->get_e();
	clus_adc    += hit->get_adc();

	double hit_location[3] = {0.0,0.0,0.0};
	geom->find_strip_center(cell->get_ladder_z_index(),
				cell->get_ladder_phi_index(),
				cell->get_binz(),
				cell->get_binphi(),
				hit_location);

	ladder_z_index = cell->get_ladder_z_index();
	ladder_phi_index = cell->get_ladder_phi_index();

	if (_make_e_weights[layer]) {
	  xsum += hit_location[0] * hit->get_adc();
	  ysum += hit_location[1] * hit->get_adc();
	  zsum += hit_location[2] * hit->get_adc();  
	} else {
	  xsum += hit_location[0];
	  ysum += hit_location[1];
	  zsum += hit_location[2];
	}
	++nhits;
      }

      double clusx = NAN;
      double clusy = NAN;
      double clusz = NAN;

      if (_make_e_weights[layer]) {
	clusx = xsum / clus_adc;
	clusy = ysum / clus_adc;
	clusz = zsum / clus_adc;	
      } else {
	clusx = xsum / nhits;
	clusy = ysum / nhits;
	clusz = zsum / nhits;
      }
      
      double ladder_location[3] = {0.0,0.0,0.0};
      geom->find_segment_center(ladder_z_index,
				ladder_phi_index,
				ladder_location);
      double ladderphi = atan2( ladder_location[1], ladder_location[0] );
      
      clus.set_position(0, clusx);
      clus.set_position(1, clusy);
      clus.set_position(2, clusz);

      clus.set_e(clus_energy);
      clus.set_adc(clus_adc);

      float invsqrt12 = 1.0/sqrt(12.0);
      
      TMatrixF DIM(3,3);
      DIM[0][0] = pow(0.5*thickness,2);
      DIM[0][1] = 0.0;
      DIM[0][2] = 0.0;
      DIM[1][0] = 0.0;
      DIM[1][1] = pow(0.5*phisize,2);
      DIM[1][2] = 0.0;
      DIM[2][0] = 0.0;
      DIM[2][1] = 0.0;
      DIM[2][2] = pow(0.5*zsize,2);

      TMatrixF ERR(3,3);
      ERR[0][0] = pow(0.5*thickness*invsqrt12,2);
      ERR[0][1] = 0.0;
      ERR[0][2] = 0.0;
      ERR[1][0] = 0.0;
      ERR[1][1] = pow(0.5*phisize*invsqrt12,2);
      ERR[1][2] = 0.0;
      ERR[2][0] = 0.0;
      ERR[2][1] = 0.0;
      ERR[2][2] = pow(0.5*zsize*invsqrt12,2);
      
      TMatrixF ROT(3,3);
      ROT[0][0] = cos(ladderphi);
      ROT[0][1] = -1.0*sin(ladderphi);
      ROT[0][2] = 0.0;
      ROT[1][0] = sin(ladderphi);
      ROT[1][1] = cos(ladderphi);
      ROT[1][2] = 0.0;
      ROT[2][0] = 0.0;
      ROT[2][1] = 0.0;
      ROT[2][2] = 1.0;

      TMatrixF TILT(3,3);
      TILT[0][0] = 1.0;
      TILT[0][1] = 0.0;
      TILT[0][2] = 0.0;
      TILT[1][0] = 0.0;
      TILT[1][1] = cos(tilt);
      TILT[1][2] = -1.0*sin(tilt);
      TILT[2][0] = 0.0;
      TILT[2][1] = sin(tilt);
      TILT[2][2] = cos(tilt);

      TMatrixF R(3,3);
      R = ROT * TILT;
      
      TMatrixF R_T(3,3);
      R_T.Transpose(R);
          
      TMatrixF COVAR_DIM(3,3);
      COVAR_DIM = R * DIM * R_T;
      
      clus.set_size( 0 , 0 , COVAR_DIM[0][0] );
      clus.set_size( 0 , 1 , COVAR_DIM[0][1] );
      clus.set_size( 0 , 2 , COVAR_DIM[0][2] );
      clus.set_size( 1 , 0 , COVAR_DIM[1][0] );
      clus.set_size( 1 , 1 , COVAR_DIM[1][1] );
      clus.set_size( 1 , 2 , COVAR_DIM[1][2] );
      clus.set_size( 2 , 0 , COVAR_DIM[2][0] );
      clus.set_size( 2 , 1 , COVAR_DIM[2][1] );
      clus.set_size( 2 , 2 , COVAR_DIM[2][2] );

      TMatrixF COVAR_ERR(3,3);
      COVAR_ERR = R * ERR * R_T;
      
      clus.set_error( 0 , 0 , COVAR_ERR[0][0] );
      clus.set_error( 0 , 1 , COVAR_ERR[0][1] );
      clus.set_error( 0 , 2 , COVAR_ERR[0][2] );
      clus.set_error( 1 , 0 , COVAR_ERR[1][0] );
      clus.set_error( 1 , 1 , COVAR_ERR[1][1] );
      clus.set_error( 1 , 2 , COVAR_ERR[1][2] );
      clus.set_error( 2 , 0 , COVAR_ERR[2][0] );
      clus.set_error( 2 , 1 , COVAR_ERR[2][1] );
      clus.set_error( 2 , 2 , COVAR_ERR[2][2] );
      
      if (clus_energy > get_threshold_by_layer(layer)) {
	SvtxCluster* ptr = _clusterlist->insert(clus);
	if (!ptr->IsValid()) {
	  static bool first = true;
	  if (first) {
	    cout << PHWHERE << "ERROR: Invalid SvtxClusters are being produced" << endl;
	    ptr->identify();
	    first = false;
	  }
	}
	
	if (verbosity>1) {
	  double radius = sqrt(clusx*clusx+clusy*clusy);
	  double clusphi = atan2(clusy,clusx);
	  cout << "r=" << radius << " phi=" << clusphi << " z=" << clusz << endl;
	  cout << "pos=(" << clus.get_position(0) << ", " << clus.get_position(1)
	       << ", " << clus.get_position(2) << ")" << endl;
	  cout << endl;
	}
      }	else if (verbosity>1) {
	double radius = sqrt(clusx*clusx+clusy*clusy);
	double clusphi = atan2(clusy,clusx);
	cout << "removed r=" << radius << " phi=" << clusphi << " z=" << clusz << endl;
	cout << "pos=(" << clus.get_position(0) << ", " << clus.get_position(1)
	     << ", " << clus.get_position(2) << ")" << endl;
	cout << endl;
      } 
    }
  }
  
  return;
}