Example #1
0
//======================================================================
//  Angle
//=======================================================================
StatusCode HTBlob::Angle( SmartRef<Minerva::IDCluster> Cluster, Gaudi::XYZVector direction, Gaudi::XYZPoint vert, double &angle ) const
{

    if ( direction.x() == -9999 || vert.x() == -9999 ) return StatusCode::FAILURE;
    double dx, dz, Dx, Dz;

    switch(Cluster->view())
    {
        case Minerva::IDCluster::X:
            dx = Cluster->position() - vert.x();
            Dx = direction.x();
            break;

        case Minerva::IDCluster::U:
            dx = Cluster->position() - m_mathTool->calcUfromXY(vert.x(),vert.y());
            Dx = m_mathTool->calcUfromXY(direction.x(),direction.y());
            break;

        case Minerva::IDCluster::V:
            dx = Cluster->position() - m_mathTool->calcVfromXY(vert.x(),vert.y());
            Dx = m_mathTool->calcVfromXY(direction.x(),direction.y());
            break;

        default:
            throw MinervaException("Unknown cluster view");

    }

    dz = Cluster->z() - vert.z();
    Dz = direction.z();

    double moduled = sqrt( pow(dx,2) + pow(dz,2) );
    double moduleD = sqrt( pow(Dx,2) + pow(Dz,2) );

    dx = dx/moduled; dz = dz/moduled;
    Dx = Dx/moduleD; Dz = Dz/moduleD;

    angle = acos(fabs(dx*Dx+dz*Dz));

    debug() << " pe = " << Cluster->pe() << "; z = " << Cluster->z() << "; pos = "  << Cluster->position()
        << " Angle " << angle << endmsg;

    return StatusCode::SUCCESS;

}
Example #2
0
//=============================================================================
//  GetDirection - Cesar Sotelo's idea 
//  Calculate direction using every cluster weighted by Energy 
//  and distance inverse weighted
//=============================================================================
bool HTBlob::GetDirection( Minerva::IDBlob *idBlob, Gaudi::XYZPoint vert ) const
{

    debug() << " HTBlob::GetDirection " << endmsg;

    SmartRefVector<Minerva::IDCluster> idClusters = idBlob->clusters();
    SmartRefVector<Minerva::IDCluster>::iterator itClus = idClusters.begin();

    double Xx = 0.0;
    double Zx = 0.0;
    double Xu = 0.0;
    double Xv = 0.0;
    double totalX = 0.0;
    double totalU = 0.0;
    double totalV = 0.0;
    double dx = 0.0;
    double dy = 0.0;
    double dz = 0.0;
    double distance = 0.0;

    for ( ; itClus != idClusters.end(); itClus++ ){

        dz = (*itClus)->z() - vert.z();

        switch((*itClus)->view())
        {
            case Minerva::IDCluster::X:
                dx = (*itClus)->position() - vert.x();
                distance = sqrt(pow(dx,2)+pow(dz,2));
                if ( distance == .0 ) distance = 25;
                Xx += dx*(*itClus)->energy()/distance;
                Zx += dz*(*itClus)->energy()/distance;
                totalX += (*itClus)->energy()/distance;
                break;

            case Minerva::IDCluster::U:
                dx = (*itClus)->position() - m_mathTool->calcUfromXY(vert.x(), vert.y());
                distance = sqrt(pow(dx,2)+pow(dz,2));
                if ( distance == .0 ) distance = 25;
                Xu += dx*(*itClus)->energy()/distance;
                totalU += (*itClus)->energy()/distance;
                break;

            case Minerva::IDCluster::V:
                dx = (*itClus)->position() - m_mathTool->calcVfromXY(vert.x(), vert.y());
                distance = sqrt(pow(dx,2)+pow(dz,2));
                if ( distance == .0 ) distance = 25;
                Xv += dx*(*itClus)->energy()/distance;
                totalV += (*itClus)->energy()/distance;
                break;

            default:
                throw MinervaException("Unknown cluster view");
        }

    }

    Gaudi::XYZVector direction;

    dx = Xx/totalX;
    dz = Zx/totalX;
    dy = -9999;
    bool valid_dY = false;
    const double epsilon = std::numeric_limits<double>::epsilon();
    if ( std::abs(Xu) > epsilon && std::abs(Xv) > epsilon ) {
        dy = m_mathTool->calcYfromUV(Xu/totalU,Xv/totalV);
        valid_dY = true;
    }
    else if ( std::abs(Xu) > epsilon ){
        dy = (dx*.5 - Xu/totalU)*2/sqrt(3); 	//calcYfromXU?
        valid_dY = true;
    }
    else if ( std::abs(Xv) > epsilon ){
        dy = (Xv/totalV - dx*.5)*2/sqrt(3); 	//calcYfromXV?
        valid_dY = true;
    }

    if  ( !valid_dY ){
        debug() << " Bad direction" << endmsg;
        idBlob->setDirection(Gaudi::XYZVector(-9999,-9999,-9999));
        return false;
    }
    else {

        double mod = sqrt( pow(dx,2)+pow(dy,2)+pow(dz,2) );

        direction.SetX(dx/mod);
        direction.SetY(dy/mod);
        direction.SetZ(dz/mod);

    }

    debug() << " Setting direction " << direction << " Blob" << idBlob << endmsg;
    idBlob->setDirection(direction);

    return true;
}
StatusCode TrackVertexMonitor::execute()
{

  LHCb::RecVertex::Range pvcontainer  = get<LHCb::RecVertex::Range>(m_pvContainerName) ;
  LHCb::Track::Range alltracks = get<LHCb::Track::Range>( m_trackContainerName );

  TrackTypePredicate isLong( LHCb::Track::Long ) ;
  TrackFlagPredicate isBackward( LHCb::Track::Backward ) ;
  TrackFlagPredicate isForward( LHCb::Track::Backward,false ) ;

  // lists needed
  // - primary vertices
  // - all tracks
  // - long tracks
  // - backward tracks
  // for now I'll just create the track lists from the Best container
  typedef std::vector<const LHCb::Track*> TrackVector ;

  // number of primary vertices
  plot(pvcontainer.size(),"NumPrimaryVertices",-0.5,10.5,11) ;

  BOOST_FOREACH( const LHCb::RecVertex* pv, pvcontainer ) {
    TrackVector tracks = myconvert(pv->tracks()) ;
    TrackVector forwardtracks = myselect(tracks,isForward) ;
    TrackVector backwardtracks =  myselect(tracks,isBackward) ;
    TrackVector longtracks =  myselect(tracks,isLong) ;

    // number of tracks per primary vertex
    plot( tracks.size(), "NumTracksPerPV",-0.5,99.5,50) ;
    // number of long tracks per primary vertex
    plot( longtracks.size(), "NumLongTracksPerPV",-0.5,99.5,50) ;
    // number of backward tracks per primary vertex
    plot( backwardtracks.size(), "NumBackTracksPerPV",-0.5,99.5,50) ;
    // chisquare
    plot( pv->chi2() / pv->nDoF(), "PV chisquare per dof",0.,3.,150) ;
    // position with crap hack for vertices at exactly 0
    if(std::abs(pv->position().x()) > 0.00001 && std::abs(pv->position().y()) > 0.00001 ){
      //info() << "pvx " << pv->position().x() << endmsg;
      plot( pv->position().x(), "PV x position",-m_rpvmax,m_rpvmax) ;
      plot( pv->position().y(), "PV y position",-m_rpvmax,m_rpvmax) ;
      plot( pv->position().z(), "PV z position", m_zpvmin,m_zpvmax) ;
      plot( pv->position().z(), "PV z position (wide)", m_zpvmin_wide,m_zpvmax_wide) ;
    }

    if( std::abs( pv->position().y() ) < m_rpvmax )
      profile1D( pv->position().z(), pv->position().y(),"PV y versus z",m_zpvmin,m_zpvmax,m_nprbins) ;
    if( std::abs( pv->position().x() ) < m_rpvmax )
      profile1D( pv->position().z(), pv->position().x(),"PV x versus z",m_zpvmin,m_zpvmax,m_nprbins) ;

    // refit the primary vertex with only the long tracks
    if(longtracks.size()>=2) {
      LHCb::RecVertex* longvertex = m_vertexer->fit( longtracks ) ;
      if(longvertex) plot( longvertex->chi2() / longvertex->nDoF(), "PV long chisquare per dof",0,10) ;
      delete longvertex ;
    }

    // now split the primary vertex in left and right tracks
    TrackVector lefttracks = myselect(tracks,TrackVeloSidePredicate(+1)) ;
    TrackVector righttracks =  myselect(tracks,TrackVeloSidePredicate(-1)) ;
    if( lefttracks.size() >= 2 && righttracks.size() >= 2 ) {
      // fit two vertices
      LHCb::RecVertex* leftvertex  = m_vertexer->fit( lefttracks ) ;

      if( leftvertex ) {
        plot( leftvertex->position().x(), "PV left x",-m_rpvmax,m_rpvmax) ;
        plot( leftvertex->position().y(), "PV left y",-m_rpvmax,m_rpvmax) ;
        plot( leftvertex->position().z(), "PV left z", m_zpvmin,m_zpvmax) ;
        if( leftSensor ) {
          plot( -(leftSensor->globalToVeloHalfBox(leftvertex->position())).x(), "PV left-Left half x",-m_rpvmax/2,m_rpvmax/2) ;
          plot( -(leftSensor->globalToVeloHalfBox(leftvertex->position())).y(), "PV left-Left half y",-m_rpvmax/2,m_rpvmax/2) ;
        }
      }
      LHCb::RecVertex* rightvertex = m_vertexer->fit( righttracks ) ;
      if( rightvertex) {
        plot( rightvertex->position().x(), "PV right x",-m_rpvmax,m_rpvmax) ;
        plot( rightvertex->position().y(), "PV right y",-m_rpvmax,m_rpvmax) ;
        plot( rightvertex->position().z(), "PV right z", m_zpvmin,m_zpvmax) ;
        if( rightSensor ) {
          plot( -(rightSensor->globalToVeloHalfBox(rightvertex->position())).x(), "PV right-Right half x",-m_rpvmax/2,m_rpvmax/2) ;
          plot( -(rightSensor->globalToVeloHalfBox(rightvertex->position())).y(), "PV right-Right half y",-m_rpvmax/2,m_rpvmax/2) ;
        }
      }
      if( leftvertex && rightvertex) {
        // draw the difference
        Gaudi::XYZVector dx = leftvertex->position() - rightvertex->position() ;

        plot( dx.x(), "PV left-right delta x",-0.1,0.1) ;
        plot( dx.y(), "PV left-right delta y",-0.1,0.1) ;
        plot( dx.z(), "PV left-right delta z",-1,1) ;
        if( std::abs( dx.y() ) < m_ipmaxprof )
          profile1D( pv->position().z(), dx.y(),"PV left-right delta y versus z",m_zpvmin,m_zpvmax,m_nprbins) ;
        if( std::abs( dx.x() ) < m_ipmaxprof )
          profile1D( pv->position().z(), dx.x(),"PV left-right delta x versus z",m_zpvmin,m_zpvmax,m_nprbins) ;

        // draw the pull of the difference
        Gaudi::SymMatrix3x3 cov = leftvertex->covMatrix() + rightvertex->covMatrix() ;
        plot( dx.x()/std::sqrt(cov(0,0)), "PV left-right delta x pull",-5,5) ;
        plot( dx.y()/std::sqrt(cov(1,1)), "PV left-right delta y pull",-5,5) ;
        plot( dx.z()/std::sqrt(cov(2,2)), "PV left-right delta z pull",-5,5) ;
        // draw the chisquares
        plot( leftvertex->chi2() / leftvertex->nDoF(), "PV left chisquare per dof",0,10) ;
        plot( rightvertex->chi2() / rightvertex->nDoF(), "PV right chisquare per dof",0,10) ;
      }
      delete leftvertex ;
      delete rightvertex ;
    }

    if( forwardtracks.size() >= 2 && backwardtracks.size() >= 2 ) {
      // fit two vertices
      LHCb::RecVertex* forwardvertex  = m_vertexer->fit( forwardtracks ) ;
      LHCb::RecVertex* backwardvertex = m_vertexer->fit( backwardtracks ) ;
      if( forwardvertex && backwardvertex) {
        Gaudi::XYZVector dx = forwardvertex->position() - backwardvertex->position() ;

        // draw the difference
        plot( dx.x(), "PV forward-backward delta x",-m_ipmax,m_ipmax) ;
        plot( dx.y(), "PV forward-backward delta y",-m_ipmax,m_ipmax) ;
        plot( dx.z(), "PV forward-backward delta z",-m_dzmax,m_dzmax) ;
        if( std::abs( dx.y() ) < m_ipmaxprof )
          profile1D( pv->position().z(), dx.y(),"PV forward-backward delta y versus z",m_zpvmin,m_zpvmax,m_nprbins) ;
        if( std::abs( dx.x() ) < m_ipmaxprof )
          profile1D( pv->position().z(), dx.x(),"PV forward-backward delta x versus z",m_zpvmin,m_zpvmax,m_nprbins) ;

        // draw the pull of the difference
        Gaudi::SymMatrix3x3 cov = forwardvertex->covMatrix() + backwardvertex->covMatrix() ;
        plot( dx.x()/std::sqrt(cov(0,0)), "PV forward-backward delta x pull",-5,5) ;
        plot( dx.y()/std::sqrt(cov(1,1)), "PV forward-backward delta y pull",-5,5) ;
        plot( dx.z()/std::sqrt(cov(2,2)), "PV forward-backward delta z pull",-5,5) ;
        // draw the chisquares
        plot( forwardvertex->chi2() / forwardvertex->nDoF(), "PV forward chisquare/dof",0,10) ;
        plot( backwardvertex->chi2() / backwardvertex->nDoF(), "PV backward chisquare/dof",0,10) ;

      }
      delete forwardvertex ;
      delete backwardvertex ;
    }

    // for events with a single vertex, do something with IP of
    // highest momentum track, as function of phi and eta.
    if( pvcontainer.size()==1 && tracks.size()>=10 ) {

      // now get all good long tracks from the best container:
      TrackVector goodlongtracks ;
      BOOST_FOREACH( const LHCb::Track* tr, alltracks )
        if( isLong(tr) && tr->chi2PerDoF()<m_maxLongTrackChisqPerDof &&
            tr->p()>m_minLongTrackMomentum)
          goodlongtracks.push_back( tr ) ;

      BOOST_FOREACH( const LHCb::Track* tr, goodlongtracks ) {
        const LHCb::State& firststate = tr->firstState() ;
        double dz  = pv->position().z() - firststate.z() ;
        double dx  = firststate.x() + dz * firststate.tx() - pv->position().x() ;
        double dy  = firststate.y() + dz * firststate.ty() - pv->position().y() ;
        Gaudi::XYZVector p3 = firststate.momentum() ;
        m_trackXIP->fill( dx ) ;
        m_trackYIP->fill( dy ) ;
        // apply a cut for the profiles
        if( std::abs(dx) < m_ipmaxprof && std::abs(dy) < m_ipmaxprof ) {
          double phi = p3.phi() ;
          double eta = p3.eta() ;
          m_trackXIPVsEta->fill(eta,dx) ;
          m_trackXIPVsPhi->fill(phi,dx) ;
          m_trackYIPVsEta->fill(eta,dy) ;
          m_trackYIPVsPhi->fill(phi,dy) ;
        }
      }

      if( goodlongtracks.size()>=2 ) {

        using namespace boost::lambda;
        std::sort(goodlongtracks.begin(), goodlongtracks.end(),
                  bind(&LHCb::State::pt,bind(&LHCb::Track::firstState,*_1)) <
                  bind(&LHCb::State::pt,bind(&LHCb::Track::firstState,*_2)) ) ;

        const LHCb::Track* firsttrack = goodlongtracks.back() ;
        goodlongtracks.pop_back() ;

        // now pick a 2nd track that makes the highest possible invariant mass with this one
        double highestmass2(0) ;
        const LHCb::Track* secondtrack(0) ;
        Gaudi::XYZVector firstp3 = firsttrack->firstState().momentum() ;
        for( TrackVector::const_iterator it = goodlongtracks.begin();
             it != goodlongtracks.end(); ++it) {
          Gaudi::XYZVector p3 = (*it)->firstState().momentum() ;
          double mass2= p3.r() * firstp3.r() - p3.Dot( firstp3 ) ;
          if(secondtrack==0 || highestmass2 < mass2 ) {
            highestmass2 = mass2 ;
            secondtrack = *it ;
          }
        }

        // recompute the vertex without these tracks
        TrackVector::iterator newend = tracks.end() ;
        newend = std::remove(tracks.begin(),newend,firsttrack) ;
        newend = std::remove(tracks.begin(),newend,secondtrack) ;
        tracks.erase(newend,tracks.end()) ;
        LHCb::RecVertex* restvertex  = m_vertexer->fit( tracks ) ;
        if( restvertex && firsttrack->nStates()!=0 ) {
          const LHCb::State& firststate = firsttrack->firstState() ;
          double dz  = restvertex->position().z() - firststate.z() ;
          double dx  = firststate.x() + dz * firststate.tx() - restvertex->position().x()  ;
          double dy  = firststate.y() + dz * firststate.ty() - restvertex->position().y() ;
          double nt  = std::sqrt( firststate.tx()*firststate.tx() + firststate.ty()*firststate.ty() ) ;
          // transverse and longitudinal impact parameter
          double iptrans = (dx * firststate.ty() - dy * firststate.tx())/nt ;
          double iplong  = (dx * firststate.tx() + dy * firststate.ty())/nt ;
          Gaudi::XYZVector p3 = firststate.momentum() ;
          double phi = p3.phi() ;
          double eta = p3.eta() ;

          m_fastTrackTransverseIP->fill(iptrans ) ;
          m_fastTrackLongitudinalIP->fill(iplong ) ;
          m_fastTrackXIP->fill( dx ) ;
          m_fastTrackYIP->fill( dy ) ;
          // apply a cut for the profiles
          if( std::abs(iptrans) < m_ipmaxprof && std::abs(iplong) < m_ipmaxprof ) {
            m_fastTrackTransverseIPVsEta->fill(eta,iptrans) ;
            m_fastTrackTransverseIPVsPhi->fill(phi,iptrans) ;
            m_fastTrackLongitudinalIPVsEta->fill(eta,iplong) ;
            m_fastTrackLongitudinalIPVsPhi->fill(phi,iplong) ;
          }
          if( std::abs(dx) < m_ipmaxprof && std::abs(dy) < m_ipmaxprof ) {
            m_fastTrackXIPVsEta->fill(eta,dx) ;
            m_fastTrackXIPVsPhi->fill(phi,dx) ;
            m_fastTrackYIPVsEta->fill(eta,dy) ;
            m_fastTrackYIPVsPhi->fill(phi,dy) ;
          }

          // The two-track cuts we only make for relatively heavy objects
          double mass = std::sqrt(highestmass2) ;
          m_twoprongMass->fill(mass / Gaudi::Units::GeV ) ;
          if( mass > 1*Gaudi::Units::GeV ) {
            // compute doca of two tracks
            Gaudi::XYZVector dx3 = firsttrack->firstState().position() - secondtrack->firstState().position() ;
            Gaudi::XYZVector n3  = firsttrack->firstState().slopes().Cross( secondtrack->firstState().slopes() ) ;
            double doca = dx3.Dot(n3) / n3.R() ;
            m_twoprongDoca->fill(doca) ;
            if( std::abs(doca) < m_twoprongDoca->axis().upperEdge() ) {
              m_twoprongDocaVsEta->fill(firstp3.eta(),doca) ;
              m_twoprongDocaVsPhi->fill(firstp3.phi(),doca) ;
            }
            // the easiest way to compute the pull is with a vertex fit
            LHCb::TwoProngVertex* twoprong = m_vertexer->fit(firsttrack->firstState(),secondtrack->firstState()) ;
            if(twoprong) {
              double pc = twoprong->p3().R() ;
              m_twoprongMomentum->fill( pc / Gaudi::Units::GeV ) ;
              m_twoprongDocaPull->fill(std::sqrt(twoprong->chi2()) * (doca>0 ? 1 : -1)) ;
              double chi2, decaylength,decaylengtherr ;
              m_vertexer->computeDecayLength( *twoprong, *restvertex, chi2, decaylength,decaylengtherr ) ;
              m_twoprongDecaylength->fill( decaylength ) ;
              m_twoprongDecaylengthSignificance->fill( decaylength/decaylengtherr ) ;
              m_twoprongIPChisquare->fill( chi2 / 2 ) ;
              m_twoprongCTau->fill( decaylength * mass / pc ) ;
              m_twoprongTau->fill( decaylength * mass / (pc * Gaudi::Units::c_light * Gaudi::Units::picosecond) ) ;
              delete twoprong ;
            }
          }
        }
        delete restvertex ;
      }
    }