SvtxTrack* TrackProjectionTools::FindClosestTrack( RawCluster* cluster, float& best_track_dr )
{

  /* best matching track */
  SvtxTrack* best_track = NULL;
  best_track_dr = NAN;

  /* find name of calorimeter for this cluster */
  string caloname = "NONE";

  /* C++11 range loop */
  for (auto& towit : cluster->get_towermap() )
    {
      caloname = RawTowerDefs::convert_caloid_to_name( RawTowerDefs::decode_caloid(towit.first) );
      break;
    }

  /* Get track collection with all tracks in this event */
  SvtxTrackMap* trackmap =
    findNode::getClass<SvtxTrackMap>(_topNode,"SvtxTrackMap_FastSim");
  if (!trackmap)
    {
      cout << PHWHERE << "SvtxTrackMap node not found on node tree"
           << endl;
    }

  /* Loop over all tracks from BARREL tracking and see if one points to the same
   * cluster as the reference clusters (i.e. matching ID in the same calorimeter) */
  /*
  for (SvtxTrackMap::ConstIter track_itr = trackmap->begin();
       track_itr != trackmap->end(); track_itr++)
    {
      SvtxTrack* track =  dynamic_cast<SvtxTrack*>(track_itr->second);
  
      if ( caloname == "CEMC" &&
           track->get_cal_cluster_id(SvtxTrack::CEMC) == cluster->get_id() )
        {
          best_track = track;
        }
    }
  */

  /* If track found with barrel tracking, return it here- if not, proceed with forward tracking below. */
  if ( best_track )
    return best_track;
  
  /* Cluster / track matching for barrel calorimeters and tracking */
  float max_dr = 10;

  /* cluster position for easy reference */
  float cx = cluster->get_x();
  float cy = cluster->get_y();

  /* If track map found: Loop over all tracks to find best match for cluster (forward calorimeters)*/
  if ( trackmap &&
       ( caloname == "FEMC" || caloname == "EEMC" ) )
    {
      for (SvtxTrackMap::ConstIter track_itr = trackmap->begin();
           track_itr != trackmap->end(); track_itr++)
        {
          /* get pointer to track */
          SvtxTrack* track =  dynamic_cast<SvtxTrack*>(track_itr->second);

          /* distance between track and cluster */
          float dr = NAN;

          /* loop over track states (projections) sotred for this track */
          for (SvtxTrack::ConstStateIter state_itr = track->begin_states();
               state_itr != track->end_states(); state_itr++)
            {
              /* get pointer to current track state */
              SvtxTrackState *temp = dynamic_cast<SvtxTrackState*>(state_itr->second);

              /* check if track state projection name matches calorimeter where cluster was found */
              if( (temp->get_name()==caloname) )
                {
                  dr = sqrt( pow( cx - temp->get_x(), 2 ) + pow( cy - temp->get_y(), 2 ) );
		  break;
                }
            }
	  
          /* check dr and update best_track and best_track_dr if this track is closest to cluster */
          if ( ( best_track_dr != best_track_dr ) ||
	       ( dr < max_dr &&
		 dr < best_track_dr )
	       )
            {
              best_track = track;
              best_track_dr = dr;
            }
        }
    }


  /* If track found with barrel tracking, return it here- if not, proceed with alternative barrel cluster-track matching below. */
  if ( best_track )
    return best_track;
  

  /* Cluster / track matching for barrel calorimeters and tracking */
  float max_dr_barrel = 10;

  float ctheta = atan2( cluster->get_r() , cluster->get_z() );
  float ceta =  -log( tan( ctheta / 2.0 ) );
  float cphi = cluster->get_phi();

  /* If track map found: Loop over all tracks to find best match for cluster (barrel calorimeters)*/
  if ( trackmap &&
       ( caloname == "CEMC" ) )
    {
      for (SvtxTrackMap::ConstIter track_itr = trackmap->begin();
           track_itr != trackmap->end(); track_itr++)
        {
          /* get pointer to track */
          SvtxTrack* track =  dynamic_cast<SvtxTrack*>(track_itr->second);

          /* distance between track and cluster */
          float dr = NAN;

          /* loop over track states (projections) sotred for this track */
          for (SvtxTrack::ConstStateIter state_itr = track->begin_states();
               state_itr != track->end_states(); state_itr++)
            {
              /* get pointer to current track state */
              SvtxTrackState *temp = dynamic_cast<SvtxTrackState*>(state_itr->second);

              /* check if track state projection name matches calorimeter where cluster was found */
              if( (temp->get_name()==caloname) )
                {
                  dr = sqrt( pow( ceta - temp->get_eta(), 2 ) + pow( cphi - temp->get_phi(), 2 ) );
                  break;
                }
            }

          /* check dr and update best_track and best_track_dr if this track is closest to cluster */
	  if ( ( best_track_dr != best_track_dr ) || 
	       (dr < max_dr_barrel &&
               dr < best_track_dr) )
            {
              best_track = track;
              best_track_dr = dr;
            }
        }
    }

  return best_track;
}