inline double get_random(AIDA::IHistogram1D& a_histo, const std::vector<double>& a_integral) { //same logic as CERN-ROOT/TH1.cxx/GetRandom(). double r = rflat_shoot(); int xbins = a_histo.axis().bins(); int ibin = binary_search(xbins,a_integral.data(),r); double x = a_histo.axis().binLowerEdge(ibin); if(r>a_integral[ibin]) { x += a_histo.axis().binWidth(ibin)* (r-a_integral[ibin])/(a_integral[ibin+1]-a_integral[ibin]); } return x; }
inline bool get_integral(AIDA::IHistogram1D& a_histo, std::vector<double>& a_integral) { a_integral.clear(); a_integral.push_back(0); int xbins = a_histo.axis().bins(); for(int index=0;index<xbins;index++) { double h = a_histo.binHeight(index); a_integral.push_back(h+a_integral.back()); } // normalize integral to 1 : double w = a_integral.back(); if(w==0) return false; std::vector<double>::iterator it; for(it=a_integral.begin();it!=a_integral.end();++it){ *it /= w; } 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 ; } }