From a1f2ed50625817bcb0709bb97e9373375a2d1593 Mon Sep 17 00:00:00 2001 From: Jeroen van Tilburg <Jeroen.van.Tilburg@cern.ch> Date: Fri, 7 Oct 2016 13:13:34 +0200 Subject: [PATCH 01/68] Updated FTMeasurement and FTHitExpectation to new FT geometry --- Tr/TrackFitEvent/src/FTMeasurement.cpp | 18 +-- Tr/TrackFitEvent/xml/FTMeasurement.xml | 4 +- Tr/TrackTools/src/FTHitExpectation.cpp | 198 ++++++++----------------- Tr/TrackTools/src/FTHitExpectation.h | 24 +-- 4 files changed, 76 insertions(+), 168 deletions(-) diff --git a/Tr/TrackFitEvent/src/FTMeasurement.cpp b/Tr/TrackFitEvent/src/FTMeasurement.cpp index d18b805574..139b861bff 100644 --- a/Tr/TrackFitEvent/src/FTMeasurement.cpp +++ b/Tr/TrackFitEvent/src/FTMeasurement.cpp @@ -5,7 +5,7 @@ // from Event #include "Event/FTCluster.h" -#include "Kernel/LineTraj.h" + // local #include "Event/FTMeasurement.h" @@ -18,17 +18,13 @@ using namespace LHCb; //----------------------------------------------------------------------------- void FTMeasurement::init( const DeFTDetector& geom ) { - const DeFTFibreMat* ftMat = geom.findFibreMat( m_cluster.channelID() ); - m_detectorElement = ftMat; - DetectorSegment mySeg = ftMat->createDetSegment( m_cluster.channelID(), m_cluster.fraction() ); - Gaudi::XYZPoint begPoint( mySeg.x( mySeg.yMin() ), mySeg.yMin(), mySeg.z( mySeg.yMin() ) ); - Gaudi::XYZPoint endPoint( mySeg.x( mySeg.yMax() ), mySeg.yMax(), mySeg.z( mySeg.yMax() ) ); - + const DeFTModule* ftModule = geom.findModule( m_cluster.channelID() ); + m_detectorElement = ftModule; m_size = m_cluster.size(); - m_errMeasure = 0.050 + .030 * m_size; - m_trajectory.reset( new LHCb::LineTraj( begPoint, endPoint ) ); - m_z = ftMat->layerCenterZ(); - m_measure = mySeg.x( 0. ); + m_errMeasure = 0.080; // + .030 * m_size; + m_trajectory = ftModule->trajectory(m_cluster.channelID(), m_cluster.fraction()); + m_z = ftModule->globalZ(); + m_measure = 0. ; // JvT: I believe this is purely historical. Should remove it? } diff --git a/Tr/TrackFitEvent/xml/FTMeasurement.xml b/Tr/TrackFitEvent/xml/FTMeasurement.xml index 35da749802..fdf1ab42bd 100644 --- a/Tr/TrackFitEvent/xml/FTMeasurement.xml +++ b/Tr/TrackFitEvent/xml/FTMeasurement.xml @@ -44,7 +44,7 @@ </code> </method> - <method + <!--method type = 'double' name = 'charge' desc = 'Retrieve the cluster charge' @@ -52,7 +52,7 @@ <code> return m_cluster.charge(); </code> - </method> + </method--> <constructor diff --git a/Tr/TrackTools/src/FTHitExpectation.cpp b/Tr/TrackTools/src/FTHitExpectation.cpp index 30bf0692ae..adc48dd349 100644 --- a/Tr/TrackTools/src/FTHitExpectation.cpp +++ b/Tr/TrackTools/src/FTHitExpectation.cpp @@ -5,18 +5,13 @@ #include "Event/Track.h" #include "Event/State.h" -//#include "Kernel/ISTChannelIDSelector.h" - // Tsa #include "TsaKernel/Line.h" #include "TsaKernel/Parabola.h" #include "TsaKernel/Line3D.h" -//#include "TsaKernel/IITExpectedHits.h" #include "LHCbMath/GeomFun.h" #include "FTDet/DeFTDetector.h" -#include "FTDet/DeFTLayer.h" -#include "FTDet/DeFTFibreMat.h" // local #include "FTHitExpectation.h" @@ -40,15 +35,9 @@ FTHitExpectation::FTHitExpectation(const std::string& type, const IInterface* parent ): THitExpectation(type, name, parent), - m_ftDet( NULL ), - m_layers(), - m_fibremats() - // m_selector(NULL) + m_ftDet( NULL ) { // constructor - //declareProperty( "SelectorType", m_selectorType = "STSelectChannelIDByElement" ); - //declareProperty( "SelectorName", m_selectorName = "ALL" ); - //declareProperty( "allStrips", m_allStrips = false); } //============================================================================= @@ -63,30 +52,14 @@ FTHitExpectation::~FTHitExpectation(){ //============================================================================= StatusCode FTHitExpectation::initialize() { - StatusCode sc = THitExpectation::initialize(); - if (sc.isFailure()){ - return Error("Failed to initialize", sc); - } - - //m_expectedITHits = tool<Tf::Tsa::IITExpectedHits>("Tf::Tsa::ITExpectedHits"); + if (sc.isFailure()) return Error("Failed to initialize", sc); - // need to know the z of T stations.... + // Get all layers (need to know the z-plane of each layer) m_ftDet = getDet<DeFTDetector>(DeFTDetectorLocation::Default); - if ( m_ftDet -> version() < 20 ){ - return Error("FTDetector version not implemented (different than v2 or v5)",StatusCode::FAILURE); - } - - m_layers = m_ftDet -> layers(); - m_fibremats = m_ftDet -> fibremats(); + if ( m_ftDet -> version() < 60 ) + return Error("This version requires FTDet v6.0 or higher", StatusCode::FAILURE); - /* - // (selector - if (m_selectorName != "ALL"){ - info() << "Selector name " << m_selectorName << endmsg; - m_selector = tool< ISTChannelIDSelector >( m_selectorType,m_selectorName ); - } - */ return StatusCode::SUCCESS; } @@ -96,135 +69,94 @@ IHitExpectation::Info FTHitExpectation::expectation(const LHCb::Track& aTrack) c IHitExpectation::Info info; info.likelihood = 0.0; info.nFound = 0; - info.nExpected = 0;; - + info.nExpected = 0; const auto& ids = aTrack.lhcbIDs(); std::vector<LHCb::LHCbID> ftHits; ftHits.reserve(ids.size()); std::copy_if( ids.begin(), ids.end(), std::back_inserter(ftHits), [](const LHCb::LHCbID& id) { return id.isFT(); } ); - for ( auto iterL = m_layers.begin(); iterL != m_layers.end() ; ++iterL ) - { - LHCb::FTChannelID elemID( (unsigned int)std::distance( m_layers.begin(), iterL ), 0u, 0u, 0u, 0u ); - double layerZ = ((*iterL)->geometry()->toGlobal( Gaudi::XYZPoint(0. ,0., 0.) )).z(); - - Tf::Tsa::Line line = yLine ( aTrack, layerZ ); - Tf::Tsa::Parabola aParab = xParabola( aTrack, layerZ ); - Tf::Tsa::Line tanLine = aParab.tangent( layerZ ); - Tf::Tsa::Line3D aLine3D = Tf::Tsa::createLine3D( tanLine, line, layerZ ); - std::vector<std::pair<LHCb::FTChannelID, double> > vectFTPairs; - - collectHits( aLine3D, elemID, vectFTPairs ); - - int old = -1; - for ( const auto& p : vectFTPairs ) - { - if ( int(p.second) != old) { - old = int(p.second); - if ( p.first ) { - ++(info.nExpected); - auto itIter = std::find( ftHits.begin(), ftHits.end(), p.first); - if (itIter != ftHits.end() ) ++info.nFound; - } - } - } // pairs - }//layers - return info; -} + // Loop over all layers + for( auto station : m_ftDet->stations() ) { + for( auto layer : station->layers() ) { -void FTHitExpectation::collectHits( Tf::Tsa::Line3D aLine3D, - LHCb::FTChannelID chan, - std::vector<std::pair<LHCb::FTChannelID, double> >& vectFTPairs - ) const{ - - for ( const auto& f : m_fibremats) - { - if( (unsigned int)(f -> layer()) != chan.layer() ) continue; - // propagate to z of sector - Gaudi::Plane3D entryplane, exitplane; - EntryExitPlanes( *f, entryplane, exitplane ); - - Gaudi::XYZPoint globalEntry = intersection( aLine3D, entryplane ); - Gaudi::XYZPoint globalExit = intersection( aLine3D, exitplane ); - - LHCb::MCHit hit; - hit.setEntry( globalEntry ); - hit.setDisplacement ( globalExit-globalEntry ); - hit.setEnergy( 1.0 ); - if( f -> isInside( hit.midPoint() ) ){ - f -> calculateHits( hit, vectFTPairs ).ignore(); + const DeFTModule* module; + Gaudi::XYZPoint intersectionPoint; + bool expectHit = findIntersectingModule(layer, aTrack, module, intersectionPoint); + + if( expectHit ) { + ++(info.nExpected); + + // Check of this layer is present in the hits + auto itIter = std::find_if( ftHits.begin(), ftHits.end(), + [&module] (const LHCb::LHCbID& id) {return id.ftID().station() == module->stationID() && + id.ftID().layer() == module->layerID(); } ); + if (itIter != ftHits.end() ) ++info.nFound; } } -} - + } -void FTHitExpectation::EntryExitPlanes( DeFTFibreMat& mat, Gaudi::Plane3D& entry, Gaudi::Plane3D& exit ) const -{ - double xmin = mat.fibreMatMinX(); - double ymin = mat.fibreMatMinY(); - double xmax = mat.fibreMatMaxX(); - double ymax = mat.fibreMatMaxY(); - - double xLower = -0.5*(xmax-xmin); - double xUpper = 0.5*(xmax-xmin); - double yLower = -0.5*(ymax-ymin); - double yUpper = 0.5*(ymax-ymin); - - const Gaudi::XYZPoint g1 = mat.geometry() -> toGlobal( Gaudi::XYZPoint( xLower, yLower, 0. ) ); - const Gaudi::XYZPoint g2 = mat.geometry() -> toGlobal( Gaudi::XYZPoint( xLower, yUpper, 0. ) ); - // trajectory of middle - //const Gaudi::XYZPoint g3 = mat.geometry()->toGlobal(xLower, 0., 0.); - const Gaudi::XYZPoint g4 = mat.geometry()->toGlobal(Gaudi::XYZPoint( xUpper, 0., 0.) ); - // plane - Gaudi::Plane3D plane(g1,g2,g4); - - double thickness = 1.2; - entry = Gaudi::Plane3D(plane.Normal(), mat.geometry()->toGlobal( Gaudi::XYZPoint(0.,0.,-0.5*thickness))); - exit = Gaudi::Plane3D(plane.Normal(), mat.geometry()->toGlobal( Gaudi::XYZPoint(0.,0., 0.5*thickness))); + return info; } -void FTHitExpectation::collect(const LHCb::Track& aTrack ,std::vector<LHCb::LHCbID>& ids) const{ +bool FTHitExpectation::findIntersectingModule(const DeFTLayer* layer, const LHCb::Track& aTrack, + const DeFTModule*& module, Gaudi::XYZPoint& intersectionPoint) const { - for ( auto iterL = m_layers.begin(); iterL != m_layers.end() ; ++iterL ) - { - LHCb::FTChannelID elemID( (unsigned int)std::distance( m_layers.begin(), iterL ), 0u, 0u, 0u, 0u ); - double layerZ = ((*iterL)->geometry()->toGlobal( Gaudi::XYZPoint(0. ,0., 0.) )).z(); + // make a Line3D from the track + double layerZ = layer->globalZ(); + Tf::Tsa::Line line = yLine ( aTrack, layerZ ); + Tf::Tsa::Parabola aParab = xParabola( aTrack, layerZ ); + Tf::Tsa::Line tanLine = aParab.tangent( layerZ ); + Tf::Tsa::Line3D aLine3D = Tf::Tsa::createLine3D( tanLine, line, layerZ ); - Tf::Tsa::Line line = yLine ( aTrack, layerZ ); - Tf::Tsa::Parabola aParab = xParabola( aTrack, layerZ ); - Tf::Tsa::Line tanLine = aParab.tangent( layerZ ); - Tf::Tsa::Line3D aLine3D = Tf::Tsa::createLine3D( tanLine, line, layerZ ); - std::vector<std::pair<LHCb::FTChannelID, double> > vectFTPairs; + // find intersection point of track and plane of layer + intersectionPoint = intersection(aLine3D, layer->plane); - collectHits( aLine3D, elemID, vectFTPairs ); + // find the module that is hit + module = layer->findModule( intersectionPoint ); + if( module == nullptr ) return false; + // find intersection point of track and plane of module + // (to account for misalignments between module and layer) + tanLine = aParab.tangent( intersectionPoint.z() ); + aLine3D = Tf::Tsa::createLine3D( tanLine, line, intersectionPoint.z() ); + intersectionPoint = intersection(aLine3D, module->plane); - int old = -1; - ids.reserve(vectFTPairs.size()); - for ( std::vector<std::pair<LHCb::FTChannelID, double> >::iterator iter = vectFTPairs.begin(); - iter != vectFTPairs.end(); - ++iter ) - { - if ( int(iter->second) != old ) { - old = int(iter->second); - if ( iter->first) ids.push_back( LHCb::LHCbID(iter->first) ); - } - } // pairs - }//layers + // check if intersection point is inside the fibres of the module + return module->isInsideSensitive( intersectionPoint ); // TODO } +void FTHitExpectation::collect(const LHCb::Track& aTrack, + std::vector<LHCb::LHCbID>& ids) const{ + // Loop over all layers + for( auto station : m_ftDet->stations() ) { + for( auto layer : station->layers() ) { + const DeFTModule* module; + Gaudi::XYZPoint intersectionPoint; + bool expectHit = findIntersectingModule(layer, aTrack, module, intersectionPoint); -unsigned int FTHitExpectation::nExpected(const LHCb::Track& aTrack) const{ + // Find the channel that is closest + Gaudi::XYZPoint localP = module->geometry()->toLocal( intersectionPoint ); + double frac; + LHCb::FTChannelID ftChan = module->calculateChannelAndFrac(localP.x(), frac); + + // Add the channels + // JvT: Without the fraction the bare FTChannelID is pretty useless... + if( std::abs(frac) <= 0.5 ) ids.push_back( LHCb::LHCbID(ftChan) ); + } + } +} + +unsigned int FTHitExpectation::nExpected(const LHCb::Track& aTrack) const{ return expectation(aTrack).nExpected; } + Gaudi::XYZPoint FTHitExpectation::intersection(const Tf::Tsa::Line3D& line, const Gaudi::Plane3D& aPlane) const{ - // make a plane Gaudi::XYZPoint inter; double mu = 0; Gaudi::Math::intersection( line, aPlane, inter, mu ); diff --git a/Tr/TrackTools/src/FTHitExpectation.h b/Tr/TrackTools/src/FTHitExpectation.h index baf230b516..b7f5c629a2 100644 --- a/Tr/TrackTools/src/FTHitExpectation.h +++ b/Tr/TrackTools/src/FTHitExpectation.h @@ -52,7 +52,6 @@ public: */ virtual unsigned int nExpected ( const LHCb::Track& aTrack ) const; - /** Returns number of hits expected * * @param aTrack Reference to the Track to test @@ -72,33 +71,14 @@ public: private: + bool findIntersectingModule(const DeFTLayer* layer, const LHCb::Track& aTrack, + const DeFTModule*& module, Gaudi::XYZPoint& intersectionPoint) const ; - //bool select(const LHCb::FTChannelID& chan) const; - - void EntryExitPlanes( DeFTFibreMat& mat, Gaudi::Plane3D& entry, Gaudi::Plane3D& exit ) const; - void collectHits( Tf::Tsa::Line3D aLine3D, - LHCb::FTChannelID chan, - std::vector<std::pair<LHCb::FTChannelID, double> >& vectFTPairs - ) const; Gaudi::XYZPoint intersection(const Tf::Tsa::Line3D& line, const Gaudi::Plane3D& aPlane) const; - DeFTDetector* m_ftDet; - std::vector<DeFTLayer*> m_layers; - std::vector<DeFTFibreMat*> m_fibremats; - - // Tf::Tsa::IITExpectedHits* m_expectedITHits; - // std::string m_selectorType; - // std::string m_selectorName; - // ISTChannelIDSelector* m_selector; - // bool m_allStrips; }; -/* -inline bool ITHitExpectation::select(const LHCb::STChannelID& chan) const{ - return m_selector == 0 ? true : m_selector->select(chan); -} -*/ #endif -- GitLab From ba99d8bae82775e025562d752fac5f3e6a76a652 Mon Sep 17 00:00:00 2001 From: Jeroen van Tilburg <Jeroen.van.Tilburg@cern.ch> Date: Tue, 11 Oct 2016 13:53:50 +0200 Subject: [PATCH 02/68] Modified PrAlgorithms, PrMCTools and TrackTools for the new FTDet --- Pr/PrAlgorithms/src/PrFTHitManager.cpp | 159 +++++++-------------- Pr/PrAlgorithms/src/PrFTHitManager.h | 8 -- Pr/PrMCTools/src/PrClustersResidual.cpp | 39 ++--- Pr/PrMCTools/src/PrDebugTrackingLosses.cpp | 3 +- Pr/PrMCTools/src/PrPlotFTHits.cpp | 14 +- Tr/TrackTools/src/FTHitExpectation.cpp | 26 ++-- 6 files changed, 81 insertions(+), 168 deletions(-) diff --git a/Pr/PrAlgorithms/src/PrFTHitManager.cpp b/Pr/PrAlgorithms/src/PrFTHitManager.cpp index 087d4840b0..8adf2efe17 100644 --- a/Pr/PrAlgorithms/src/PrFTHitManager.cpp +++ b/Pr/PrAlgorithms/src/PrFTHitManager.cpp @@ -6,8 +6,6 @@ // local #include "PrFTHitManager.h" -//#include "Kernel/FTChannelID.h" - //----------------------------------------------------------------------------- // Implementation file for class : PrFTHitManager // @@ -17,19 +15,15 @@ // Declaration of the Tool Factory DECLARE_TOOL_FACTORY( PrFTHitManager ) - //============================================================================= // Standard constructor, initializes variables //============================================================================= PrFTHitManager::PrFTHitManager( const std::string& type, - const std::string& name, - const IInterface* parent ) + const std::string& name, + const IInterface* parent ) : PrHitManager ( type, name , parent ) { declareInterface<PrFTHitManager>(this); - declareProperty( "XSmearing", m_xSmearing = -1. ); - declareProperty( "ZSmearing", m_zSmearing = -1. ); - } //========================================================================= @@ -39,58 +33,38 @@ void PrFTHitManager::buildGeometry ( ) { // -- only build geometry once. if(m_geometryBuilt) return; - - IRndmGenSvc* randSvc = svc<IRndmGenSvc>( "RndmGenSvc", true ); - StatusCode sc = m_gauss.initialize( randSvc, Rndm::Gauss( 0., 1. ) ); - if ( sc.isFailure() ){ - error() << "Could not initialize Rndm::Gauss generator" << endmsg; + // Retrieve and initialize DeFT (no test: exception in case of failure) + m_ftDet = getDet<DeFTDetector>( DeFTDetectorLocation::Default ); + if( m_ftDet->version() < 60 ) { + error() << "This version requires FTDet v6.0 or higher" << endmsg; return; } - - - m_ftDet = getDet<DeFTDetector>( DeFTDetectorLocation::Default ); - //version 20 is the detector with monolayer and fibremat structure, including the dead regions - if ( msgLevel( MSG::DEBUG) ) debug() << "DETECTOR VERSION: " << m_ftDet->version() << endmsg; - //Different Detector Segments has to be used to set the geometry of zone Up and Down to be consistent with new DeFTFibreMat - DetectorSegment segUp; - DetectorSegment segDown; - for ( std::vector<DeFTLayer*>::const_iterator itL = m_ftDet->layers().begin(); //loop over layers - m_ftDet->layers().end() != itL; ++itL ) { - int id = (*itL)->params()->param<int>("layerID"); //ask layerID - - //FTChannelID (layer,module,mat,SiPMID,netCellID) - LHCb::FTChannelID ChUp( id, 0u, 0u, 0u, 0u ); //"0u" means "unsigned 0" - const DeFTFibreMat* ftMatUp = m_ftDet->findFibreMat(ChUp); - segUp = ftMatUp->createDetSegment( ChUp, 0. ); - - LHCb::FTChannelID ChDown( id, 0u, 1u, 0u, 0u ); //"0u" means "unsigned 0" - const DeFTFibreMat* ftMatDown = m_ftDet->findFibreMat(ChDown); - segDown = ftMatDown->createDetSegment( ChDown, 0. ); - - if ( msgLevel( MSG::DEBUG) ) debug() << "STEREO ANGLE Up: " << ftMatUp->angle() << endmsg; - if ( msgLevel( MSG::DEBUG) ) debug() << "STEREO ANGLE Down: " << ftMatDown->angle() << endmsg; - - //The setGeometry defines the z at y=0, the dxDy and the dzDy, as well as the isX properties of the zone. - //This is important, since these are used in the following. - //They are set once for each zone in this method. - zone( 2*id )->setGeometry( segUp ); // ex:layers 0 down (up with new FTChannelID) - zone( 2*id+1 )->setGeometry( segDown ); // ex:layers 0 up (down with new FTChannelID) - //The boundaries are needed in case you will use the m_xMin, m_xMax, m_yMin, m_yMax of the zone, - //or methods that are indirectly using them, like dxOnAFibre() or isInside(x,y) - //(see https://svnweb.cern.ch/trac/lhcb/browser/Rec/trunk/Pr/PrKernel/PrKernel/PrHitZone.h?rev=164716). - //These are currently not used anywhere in the seeding algorithm. - //The isInside(x,y) method is used in the forward algorithm. - zone( 2*id+1 )->setBoundaries( -4090., 4090., -3030., 50. ); //check these boudaries for zone down (with new FTChannelID) - zone( 2*id )->setBoundaries( -4090., 4090., -50., 3030. ); //check these boudaries for zone up (with new FTChannelID) - if ( msgLevel( MSG::DEBUG) ) debug() << "Layer " << id << " z " << zone(2*id)->z() - << " angle " << zone(2*id)->dxDy() << endmsg; + + // Loop over all layers + for( auto station : m_ftDet->stations() ) { + for( auto layer : station->layers() ) { + int id = 4*(station->stationID() - 1) + layer->layerID(); + + DetectorSegment seg(0, layer->globalZ(), layer->dxdy(), layer->dzdy(), 0., 0.); + zone( 2*id )->setGeometry( seg ); + zone( 2*id+1 )->setGeometry( seg ); + + //The boundaries are needed in case you will use the m_xMin, m_xMax, m_yMin, m_yMax of the zone, + //or methods that are indirectly using them, like dxOnAFibre() or isInside(x,y) + //(see https://svnweb.cern.ch/trac/lhcb/browser/Rec/trunk/Pr/PrKernel/PrKernel/PrHitZone.h?rev=164716). + //These are currently not used anywhere in the seeding algorithm. + //The isInside(x,y) method is used in the forward algorithm. + float xmax = 0.5*layer->sizeX(); + float ymax = 0.5*layer->sizeY(); + zone( 2*id+1 )->setBoundaries( -xmax, xmax, -ymax, 25. ); // Small overlap (25 mm) for stereo layers + zone( 2*id )->setBoundaries( -xmax, xmax, -25., ymax ); // Small overlap (25 mm) for stereo layers + if ( msgLevel( MSG::DEBUG) ) debug() << "Layer " << id << " z " << zone(2*id)->z() + << " angle " << zone(2*id)->dxDy() << endmsg; + } } - if ( msgLevel( MSG::DEBUG) ) debug() << "XSmearing " << m_xSmearing << " ZSmearing " << m_zSmearing << endmsg; m_geometryBuilt = true; - - } @@ -100,72 +74,43 @@ void PrFTHitManager::buildGeometry ( ) { void PrFTHitManager::decodeData ( ) { if(m_decodedData) return; - - if ( msgLevel( MSG::DEBUG) ) debug() << "I AM IN DECODEDATA " << endmsg; typedef FastClusterContainer<LHCb::FTLiteCluster,int> FTLiteClusters; - FTLiteClusters* clus = get<FTLiteClusters>( LHCb::FTLiteClusterLocation::Default ); - if ( msgLevel( MSG::DEBUG) ) debug() << "Retrieved " << clus->size() << " clusters" << endmsg; - const DeFTFibreMat* ftMat = nullptr; - const DeFTFibreMat* anaFtMat = nullptr; - unsigned int oldFibreMatID = 99999999; - - DetectorSegment seg ; + FTLiteClusters* clusters = get<FTLiteClusters>( LHCb::FTLiteClusterLocation::Default ); + if ( msgLevel( MSG::DEBUG) ) debug() << "Retrieved " << clusters->size() << " clusters" << endmsg; - for ( FTLiteClusters::iterator itC = clus->begin(); clus->end() != itC; ++itC ) { - /// find fibremat to which the cluster belongs - anaFtMat = m_ftDet->findFibreMat( (*itC).channelID() ); - if(anaFtMat->FibreMatID() != oldFibreMatID) { - oldFibreMatID = anaFtMat->FibreMatID(); - ftMat = anaFtMat; - if ( nullptr == ftMat ) { - info() << "FiberMat not found for FT channelID " << (*itC).channelID() << endmsg; - oldFibreMatID = 99999999; - } + const DeFTModule* module = nullptr; + unsigned int prevModuleID = 99999999; + for ( auto clus : *clusters ) { + if( clus.channelID().uniqueModule() != prevModuleID ) { + module = m_ftDet->findModule( clus.channelID() ); + prevModuleID = module->elementID().uniqueModule(); } + double fraction = clus.fraction(); + LHCb::FTChannelID id = clus.channelID(); - - double fraction = (*itC).fraction() + 0.125; // Truncated to 4 bits = 0.25. Add half of it - LHCb::FTChannelID id = (*itC).channelID(); - - int lay = (*itC).channelID().layer(); - int zone = (int)((*itC).channelID().mat() > 0); //if yes, it is bottom (now bottom is 1) + int lay = 4*(id.station()-1) + id.layer(); + int zone = int(module->isBottom()); int code = 2*lay + zone; - //variables - const double fibreMatHalfSizeY = ftMat->getFibreMatHalfSizeY(); - const double cellSizeX = ftMat->getCellSizeX(); - const float dzDy = ftMat->getDzDy(); - const float dxDy = -ftMat->getTanAngle();// = -m_tanAngle - const double hitLocalX = ftMat->cellLocalX(id) + fraction*cellSizeX; - double xx, xy, xz, dx, yx, yy, yz, dy, zx, zy, zz, dz; - ftMat->geometry()->toGlobalMatrix().GetComponents( xx, xy, xz, dx, yx, yy, yz, dy, zx, zy, zz, dz ); - - //const float yBorder = yx* hitLocalX + yy * (2*zone-1)*fibreMatHalfSizeY + dy; - const float yMin = yx* hitLocalX - yy *fibreMatHalfSizeY + dy; - const float yMax = yx* hitLocalX + yy *fibreMatHalfSizeY + dy; - - //calculate hit x,z at y=0 in global frame (as local y=0 NOT global y=0) - const double hitGlobala_X = hitLocalX * xx + dx; - const double hitGlobalb_X = hitGlobala_X + fibreMatHalfSizeY*xy; - const double hitGlobala_Y = hitLocalX * yx+ dy; - const double hitGlobalb_Y = hitGlobala_Y + fibreMatHalfSizeY*yy; - const double hitGlobala_Z = hitLocalX * zx + dz; - const double hitGlobalb_Z = hitGlobala_Z + fibreMatHalfSizeY*zy; - const double axy = (hitGlobala_X-hitGlobalb_X)/(hitGlobala_Y-hitGlobalb_Y); - const double azy = (hitGlobala_Z-hitGlobalb_Z)/(hitGlobala_Y-hitGlobalb_Y); - const float x0 = hitGlobalb_X-axy*hitGlobalb_Y; - const float z0 = hitGlobalb_Z-azy*hitGlobalb_Y; + auto endPoints = module->endPoints(id, fraction); + double invdy = 1./(endPoints.first.x()-endPoints.second.x()); + double dxdy = (endPoints.first.x()-endPoints.second.x())*invdy; + double dzdy = (endPoints.first.z()-endPoints.second.z())*invdy; + float x0 = endPoints.first.x()-dxdy*endPoints.first.y(); + float z0 = endPoints.first.z()-dzdy*endPoints.first.y(); + float yMin = std::min(endPoints.first.y(), endPoints.second.y()); + float yMax = std::max(endPoints.first.y(), endPoints.second.y()); PrHit* aHit = newHitInZone( code ); - float errX = 0.05 + .03 * (*itC).size(); - aHit->setHit( LHCb::LHCbID( (*itC).channelID() ), x0, z0, dxDy, dzDy, yMin, yMax, errX , zone, lay ); + float errX = 0.08; // TODO: get this from a tool + aHit->setHit( LHCb::LHCbID( id ), x0, z0, dxdy, dzdy, yMin, yMax, errX , zone, lay ); - if ( UNLIKELY(msgLevel( MSG::DEBUG)) ) info() << " .. hit " << (*itC).channelID() << " zone " << zone << " x " << seg.x(0.) << endmsg; + if ( UNLIKELY(msgLevel( MSG::VERBOSE)) ) + verbose() << " .. hit " << id << " zone " << zone << " x " << x0 << endmsg; } - for ( unsigned int lay = 0; nbZones() > lay ; ++lay ) { std::sort( getIterator_Begin(lay), getIterator_End(lay), PrHit::LowerByX0() ); } diff --git a/Pr/PrAlgorithms/src/PrFTHitManager.h b/Pr/PrAlgorithms/src/PrFTHitManager.h index 7107b32301..dc63b6830f 100644 --- a/Pr/PrAlgorithms/src/PrFTHitManager.h +++ b/Pr/PrAlgorithms/src/PrFTHitManager.h @@ -12,10 +12,6 @@ static const InterfaceID IID_PrFTHitManager ( "PrFTHitManager", 1, 0 ); /** @class PrFTHitManager PrFTHitManager.h * Tool that transforms clusters into 'hits' (spatial positions) which are then used by the pattern * recognition algorithms involving the FT. - * - * Parameters: - * - XSmearing: Amount of gaussian smearing in x - * - ZSmearing: Switch on displacement in z (not used at the moment) * * @author Olivier Callot * @date 2012-03-13 @@ -38,14 +34,10 @@ public: /** @brief Construct the hits and apply smearing to hit position (if enabled) */ void decodeData(); - protected: private: DeFTDetector* m_ftDet; - Rndm::Numbers m_gauss; ///< Random number generator for gaussian smearing - float m_xSmearing; ///< Amount of smearing in x - float m_zSmearing; }; #endif // PRFTHITMANAGER_H diff --git a/Pr/PrMCTools/src/PrClustersResidual.cpp b/Pr/PrMCTools/src/PrClustersResidual.cpp index 87d550ca37..18b332a1a3 100644 --- a/Pr/PrMCTools/src/PrClustersResidual.cpp +++ b/Pr/PrMCTools/src/PrClustersResidual.cpp @@ -1,4 +1,4 @@ -// Include files +// Include files // from Gaudi #include "GaudiKernel/AlgFactory.h" @@ -178,21 +178,7 @@ void PrClustersResidual::Occupancy(){ hit = &(*itH); nHits[layer]++; LHCb::FTLiteCluster liteCluster = getLiteCluster(hit->id()); - // int SipmCell = liteCluster.channelID().sipmCell(); - int Module = liteCluster.channelID().module(); - int Quarter = liteCluster.channelID().quarter(); - // int Mat = liteCluster.channelID().mat(); - int SipmID = liteCluster.channelID().sipmId(); - int layer = liteCluster.channelID().layer(); - int module2 = Module; - if(Module == 11 && Module > 4 ) module2 = 1; - if(Module != 11 && Module > 4 ) module2 = Module-3; - if(Module < 5 ) module2 = 6-Module; - if(Module == 10 ) module2 = 1; - int index = Quarter*128 + 16*module2+ std::floor(SipmID); - // if(index<0 || index>){ - // always()<<"Problem in Sipm Index; Correct for that"<<endmsg; - // } + int index = liteCluster.channelID().uniqueSiPM() & 511; sprintf(layerName,"Layer%i/AllContributions",layer); sprintf(Title,"Sipm Index Layer %i;SiPm Id;Clusters/Sipm/Event",layer); plot1D(index,layerName,Title,0.5,512.5,512); @@ -426,12 +412,11 @@ void PrClustersResidual::TrackStudy(){ //ChannelID of track hits std::vector<double> ChID_Fraction; - std::vector<double> ChID_Charge; std::vector<double> ChID_SipmCell; std::vector<double> ChID_Module; std::vector<double> ChID_Layer; std::vector<double> ChID_Quarter; - std::vector<double> ChID_Mat; + std::vector<double> ChID_Station; std::vector<double> ChID_SipmID; std::vector<double> ChID_ID; @@ -484,14 +469,13 @@ void PrClustersResidual::TrackStudy(){ } LHCb::FTLiteCluster liteCluster = getLiteCluster(hit->id()); ChID_Fraction.push_back(liteCluster.fraction()); - ChID_SipmCell.push_back(liteCluster.channelID().sipmCell()); + ChID_SipmCell.push_back(liteCluster.channelID().channel()); ChID_Module.push_back(liteCluster.channelID().module()); ChID_Layer.push_back(liteCluster.channelID().layer()); ChID_Quarter.push_back(liteCluster.channelID().quarter()); - ChID_Mat.push_back(liteCluster.channelID().mat()); - ChID_SipmID.push_back(liteCluster.channelID().sipmId()); + ChID_Station.push_back(liteCluster.channelID().station()); + ChID_SipmID.push_back(liteCluster.channelID().sipm()); ChID_ID.push_back(liteCluster.channelID()); - ChID_Charge.push_back(liteCluster.charge()); PrHit_LHCBID.push_back(hit->id().ftID()); PrHit_Xat0.push_back(hit->x()); PrHit_Zat0.push_back(hit->z()); @@ -558,8 +542,7 @@ void PrClustersResidual::TrackStudy(){ tuple->farray("ChID_Module",ChID_Module,"ChID",100); tuple->farray("ChID_Layer",ChID_Layer,"ChID",100); tuple->farray("ChID_Quarter",ChID_Quarter,"ChID",100); - tuple->farray("ChID_Charge",ChID_Charge,"ChID",100); - tuple->farray("ChID_Mat",ChID_Mat,"ChID",100); + tuple->farray("ChID_Station",ChID_Station,"ChID",100); tuple->farray("ChID_SipmID",ChID_SipmID,"ChID",100); tuple->farray("ChID_ID",ChID_ID,"ChID",100); @@ -1082,13 +1065,12 @@ void PrClustersResidual::ClusterResidual(){ //get Cluster associated to the Hit if(msgLevel(MSG::DEBUG)) debug()<<"Getting LiteCluster from PrHit"<<endmsg; LHCb::FTLiteCluster litecluster = getLiteCluster( (*iHit).id()); - tuple->column("ClusterCharge",litecluster.charge()); tuple->column("ClusterSize",litecluster.size()); tuple->column("ClusterFraction",litecluster.fraction()); tuple->column("ClusterChannelID",litecluster.channelID()); - tuple->column("ClusterChannelIDSipmCell",litecluster.channelID().sipmCell()); - tuple->column("ClusterChannelIDSipmID",litecluster.channelID().sipmId()); - tuple->column("ClusterChannelIDMat",litecluster.channelID().mat()); + tuple->column("ClusterChannelIDSipmCell",litecluster.channelID().channel()); + tuple->column("ClusterChannelIDSipmID",litecluster.channelID().sipm()); + tuple->column("ClusterChannelIDStation",litecluster.channelID().station()); tuple->column("ClusterChannelIDModule",litecluster.channelID().module()); tuple->column("ClusterChannelLayer",litecluster.channelID().layer()); tuple->column("ClusterChannelQuarter",litecluster.channelID().quarter()); @@ -1294,3 +1276,4 @@ LHCb::FTLiteCluster PrClustersResidual::getLiteCluster(const LHCb::LHCbID id) return idTracks; } + diff --git a/Pr/PrMCTools/src/PrDebugTrackingLosses.cpp b/Pr/PrMCTools/src/PrDebugTrackingLosses.cpp index e17b7ccae0..04c86ba89f 100644 --- a/Pr/PrMCTools/src/PrDebugTrackingLosses.cpp +++ b/Pr/PrMCTools/src/PrDebugTrackingLosses.cpp @@ -218,7 +218,7 @@ StatusCode PrDebugTrackingLosses::execute() { } else if ( (*itId).isFT() ) { LHCb::FTChannelID ftID = (*itId).ftID(); info() << format( " FT St%2d La%2d Pm%2d Cel%4d ", - ftID.layer()/4, ftID.layer()&3, ftID.sipmId(), ftID.sipmCell() ); + ftID.station(), ftID.layer(), ftID.sipm(), ftID.channel() ); } else if ( (*itId).isOT() ) { LHCb::OTChannelID otID = (*itId).otID(); info() << format( " OT St%2d La%2d mo%2d Str%4d ", @@ -285,3 +285,4 @@ StatusCode PrDebugTrackingLosses::finalize() { } //============================================================================= + diff --git a/Pr/PrMCTools/src/PrPlotFTHits.cpp b/Pr/PrMCTools/src/PrPlotFTHits.cpp index dda0e2d213..bfb5b0da90 100644 --- a/Pr/PrMCTools/src/PrPlotFTHits.cpp +++ b/Pr/PrMCTools/src/PrPlotFTHits.cpp @@ -164,19 +164,7 @@ void PrPlotFTHits::plotOccupancy(){ hit = &*itH; nHits[layer]++; LHCb::FTLiteCluster liteCluster = getLiteCluster(hit->id()); - int Module = liteCluster.channelID().module(); - int Quarter = liteCluster.channelID().quarter(); - int SipmID = liteCluster.channelID().sipmId(); - int layer = liteCluster.channelID().layer(); - int module2 = Module; - if(Module == 11 && Module > 4 ) module2 = 1; - if(Module != 11 && Module > 4 ) module2 = Module-3; - if(Module < 5 ) module2 = 6-Module; - if(Module == 10 ) module2 = 1; - int index = Quarter*128 + 16*module2+ std::floor(SipmID); - // if(index<0 || index>){ - // always()<<"Problem in Sipm Index; Correct for that"<<endmsg; - // } + int index = liteCluster.channelID().uniqueSiPM() & 511; sprintf(layerName,"Layer%i/AllContributions",layer); sprintf(Title,"Sipm Index Layer %i;SiPm Id;Clusters/Sipm/Event",layer); m_histoTool->plot1D(index,layerName,Title,0.5,512.5,512); diff --git a/Tr/TrackTools/src/FTHitExpectation.cpp b/Tr/TrackTools/src/FTHitExpectation.cpp index adc48dd349..aed5a2c5b3 100644 --- a/Tr/TrackTools/src/FTHitExpectation.cpp +++ b/Tr/TrackTools/src/FTHitExpectation.cpp @@ -111,7 +111,8 @@ bool FTHitExpectation::findIntersectingModule(const DeFTLayer* layer, const LHCb Tf::Tsa::Line3D aLine3D = Tf::Tsa::createLine3D( tanLine, line, layerZ ); // find intersection point of track and plane of layer - intersectionPoint = intersection(aLine3D, layer->plane); + const Gaudi::Plane3D layerPlane = layer->plane(); + intersectionPoint = intersection(aLine3D, layerPlane); // find the module that is hit module = layer->findModule( intersectionPoint ); @@ -121,10 +122,11 @@ bool FTHitExpectation::findIntersectingModule(const DeFTLayer* layer, const LHCb // (to account for misalignments between module and layer) tanLine = aParab.tangent( intersectionPoint.z() ); aLine3D = Tf::Tsa::createLine3D( tanLine, line, intersectionPoint.z() ); - intersectionPoint = intersection(aLine3D, module->plane); + const Gaudi::Plane3D modulePlane = module->plane(); + intersectionPoint = intersection(aLine3D, modulePlane); // check if intersection point is inside the fibres of the module - return module->isInsideSensitive( intersectionPoint ); // TODO + return module->isInsideSensitive( intersectionPoint ); } void FTHitExpectation::collect(const LHCb::Track& aTrack, @@ -137,14 +139,16 @@ void FTHitExpectation::collect(const LHCb::Track& aTrack, Gaudi::XYZPoint intersectionPoint; bool expectHit = findIntersectingModule(layer, aTrack, module, intersectionPoint); - // Find the channel that is closest - Gaudi::XYZPoint localP = module->geometry()->toLocal( intersectionPoint ); - double frac; - LHCb::FTChannelID ftChan = module->calculateChannelAndFrac(localP.x(), frac); - - // Add the channels - // JvT: Without the fraction the bare FTChannelID is pretty useless... - if( std::abs(frac) <= 0.5 ) ids.push_back( LHCb::LHCbID(ftChan) ); + if( expectHit ) { + // Find the channel that is closest + Gaudi::XYZPoint localP = module->geometry()->toLocal( intersectionPoint ); + double frac; + LHCb::FTChannelID ftChan = module->calculateChannelAndFrac(localP.x(), frac); + + // Add the channels + // JvT: Without the fraction the bare FTChannelID is pretty useless... + if( std::abs(frac) <= 0.5 ) ids.push_back( LHCb::LHCbID(ftChan) ); + } } } } -- GitLab From 01da6dea5160627f9b2e1eabea0141ee19cbb5e7 Mon Sep 17 00:00:00 2001 From: Jeroen van Tilburg <Jeroen.van.Tilburg@cern.ch> Date: Thu, 13 Oct 2016 13:20:16 +0200 Subject: [PATCH 03/68] Fix typo in PrFTHitManager --- Pr/PrAlgorithms/src/PrFTHitManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Pr/PrAlgorithms/src/PrFTHitManager.cpp b/Pr/PrAlgorithms/src/PrFTHitManager.cpp index 8adf2efe17..727f484c7d 100644 --- a/Pr/PrAlgorithms/src/PrFTHitManager.cpp +++ b/Pr/PrAlgorithms/src/PrFTHitManager.cpp @@ -95,7 +95,7 @@ void PrFTHitManager::decodeData ( ) { int code = 2*lay + zone; auto endPoints = module->endPoints(id, fraction); - double invdy = 1./(endPoints.first.x()-endPoints.second.x()); + double invdy = 1./(endPoints.first.y()-endPoints.second.y()); double dxdy = (endPoints.first.x()-endPoints.second.x())*invdy; double dzdy = (endPoints.first.z()-endPoints.second.z())*invdy; float x0 = endPoints.first.x()-dxdy*endPoints.first.y(); -- GitLab From 3de64676c68a1913b614cd6f139d2cc6e986a6ad Mon Sep 17 00:00:00 2001 From: Jeroen van Tilburg <Jeroen.van.Tilburg@cern.ch> Date: Thu, 13 Oct 2016 17:41:30 +0200 Subject: [PATCH 04/68] Fixed -> in PrFTHitManager --- Pr/PrAlgorithms/src/PrFTHitManager.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/Pr/PrAlgorithms/src/PrFTHitManager.cpp b/Pr/PrAlgorithms/src/PrFTHitManager.cpp index 4c256892de..602653ddce 100644 --- a/Pr/PrAlgorithms/src/PrFTHitManager.cpp +++ b/Pr/PrAlgorithms/src/PrFTHitManager.cpp @@ -55,8 +55,12 @@ void PrFTHitManager::buildGeometry ( ) { MakeZone( 2*id, seg, -xmax, xmax, -25., ymax ); // Small overlap (25 mm) for stereo layers MakeZone( 2*id+1, seg, -xmax, xmax, -ymax, 25. ); // Small overlap (25 mm) for stereo layers - if ( msgLevel( MSG::DEBUG) ) debug() << "Layer " << id << " z " << zone(2*id)->z() - << " angle " << zone(2*id)->dxDy() << endmsg; + //----> Debug zones + if( msgLevel(MSG::DEBUG)){ + debug() << "Layer " << id << " z " << zone(2*id).z() + << " angle " << zone(2*id).dxDy() << endmsg; + } + //----> Debug zones } } @@ -101,8 +105,7 @@ void PrFTHitManager::decodeData ( ) { float errX = 0.08; // TODO: get this from a tool addHitInZone( code, LHCb::LHCbID( id ), x0, z0, dxdy, dzdy, yMin, yMax, errX , zone, lay ); - - if ( UNLIKELY(msgLevel( MSG::VERBOSE)) ) + if ( msgLevel(MSG::VERBOSE) ) verbose() << " .. hit " << id << " zone " << zone << " x " << x0 << endmsg; } -- GitLab From 7105dc03cbd4d3bdb51d24a8e3ab859e324c8429 Mon Sep 17 00:00:00 2001 From: Jeroen van Tilburg <Jeroen.van.Tilburg@cern.ch> Date: Thu, 13 Oct 2016 18:03:23 +0200 Subject: [PATCH 05/68] Changed resolution to 140 micron --- Pr/PrAlgorithms/src/PrFTHitManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Pr/PrAlgorithms/src/PrFTHitManager.cpp b/Pr/PrAlgorithms/src/PrFTHitManager.cpp index 602653ddce..6b42d79a75 100644 --- a/Pr/PrAlgorithms/src/PrFTHitManager.cpp +++ b/Pr/PrAlgorithms/src/PrFTHitManager.cpp @@ -103,7 +103,7 @@ void PrFTHitManager::decodeData ( ) { float yMin = std::min(endPoints.first.y(), endPoints.second.y()); float yMax = std::max(endPoints.first.y(), endPoints.second.y()); - float errX = 0.08; // TODO: get this from a tool + float errX = 0.14; // TODO: get this from a tool addHitInZone( code, LHCb::LHCbID( id ), x0, z0, dxdy, dzdy, yMin, yMax, errX , zone, lay ); if ( msgLevel(MSG::VERBOSE) ) verbose() << " .. hit " << id << " zone " << zone << " x " << x0 << endmsg; -- GitLab From 6ec74b7a7f6a28217161652341e29aef2d4c8677 Mon Sep 17 00:00:00 2001 From: Jeroen van Tilburg <Jeroen.van.Tilburg@cern.ch> Date: Wed, 19 Oct 2016 09:28:27 +0200 Subject: [PATCH 06/68] Change PrHit resolution to 170 micron in PrFTHitManager. Removed unnecessary sort in FTMeasurementProvider. Adjusted plot ranges in PrClustersResidual. --- Pr/PrAlgorithms/src/PrFTHitManager.cpp | 2 +- Pr/PrMCTools/src/PrClustersResidual.cpp | 12 ++++---- Tr/TrackTools/src/FTMeasurementProvider.cpp | 32 +++++++++++---------- 3 files changed, 24 insertions(+), 22 deletions(-) diff --git a/Pr/PrAlgorithms/src/PrFTHitManager.cpp b/Pr/PrAlgorithms/src/PrFTHitManager.cpp index 6b42d79a75..8f4639ba2c 100644 --- a/Pr/PrAlgorithms/src/PrFTHitManager.cpp +++ b/Pr/PrAlgorithms/src/PrFTHitManager.cpp @@ -103,7 +103,7 @@ void PrFTHitManager::decodeData ( ) { float yMin = std::min(endPoints.first.y(), endPoints.second.y()); float yMax = std::max(endPoints.first.y(), endPoints.second.y()); - float errX = 0.14; // TODO: get this from a tool + float errX = 0.17; // TODO: this should be ~80 micron; get this from a tool addHitInZone( code, LHCb::LHCbID( id ), x0, z0, dxdy, dzdy, yMin, yMax, errX , zone, lay ); if ( msgLevel(MSG::VERBOSE) ) verbose() << " .. hit " << id << " zone " << zone << " x " << x0 << endmsg; diff --git a/Pr/PrMCTools/src/PrClustersResidual.cpp b/Pr/PrMCTools/src/PrClustersResidual.cpp index 18b332a1a3..faaf8592bc 100644 --- a/Pr/PrMCTools/src/PrClustersResidual.cpp +++ b/Pr/PrMCTools/src/PrClustersResidual.cpp @@ -201,29 +201,29 @@ void PrClustersResidual::Occupancy(){ if(RecobleMCParticle){ sprintf(layerName,"Layer%i/FromRecobleMCParticle",layer); sprintf(Title,"Sipm Index Layer %i;Sipm ID;Clusters/Sipm/Event",layer); - plot1D( index,layerName,Title,0.5,512.5,512); + plot1D( index,layerName,Title,-0.5,511.5,512); //0.5,96.5,96); if(mcPart->originVertex()->isPrimary() || mcPart->originVertex()->isDecay()){ sprintf(layerName,"Layer%i/FromRecobleMCParticleWanted",layer); sprintf(Title,"Sipm Index Layer %i;Sipm ID;Clusters/Sipm/Event",layer); - plot1D( index,layerName,Title,0.5,512.5,512); + plot1D( index,layerName,Title,-0.5,511.5,512); } } if(fromMCParticleContrib){ sprintf(layerName,"Layer%i/FromMCParticle",layer); sprintf(Title,"Sipm Index Layer %i;Sipm ID;Clusters/Sipm/Event",layer); - plot1D( index,layerName,Title,0.5,512.5,512);//0.5,96.5,96); + plot1D( index,layerName,Title,-0.5,511.5,512);//0.5,96.5,96); } if(NoiseCluster){ sprintf(layerName,"Layer%i/FromNoise",layer); sprintf(Title,"Sipm Index Layer %i;Sipm ID;Clusters/Sipm/Event",layer); - plot1D(index,layerName,Title,0.5,512.5,512);//0.5,96.5,96); + plot1D(index,layerName,Title,-0.5,511.5,512);//0.5,96.5,96); } if(spillCluster) { sprintf(layerName,"Layer%i/FromSpill",layer); sprintf(Title,"Sipm Index Layer %i;Sipm ID;Clusters/Sipm/Event",layer); - plot1D(index,layerName,Title,0.5,96.5,96); + plot1D(index,layerName,Title,-0.5,511.5,512); } } } @@ -1023,7 +1023,7 @@ void PrClustersResidual::ClusterResidual(){ nMCHitToCluster++; Gaudi::XYZPoint pMid = mcHit->midPoint(); Residual_X.push_back( (*iHit).x(pMid.y()) - pMid.x()); //x at y - y at z - Residual_Z.push_back( (*iHit).z(pMid.z()) - pMid.y()); + Residual_Z.push_back( (*iHit).z(pMid.y()) - pMid.y()); SlopeX.push_back( mcHit->dxdz()); SlopeY.push_back( mcHit->dydz()); pathlength.push_back( mcHit->pathLength()); diff --git a/Tr/TrackTools/src/FTMeasurementProvider.cpp b/Tr/TrackTools/src/FTMeasurementProvider.cpp index 8ca833120a..b2dda2eb4b 100644 --- a/Tr/TrackTools/src/FTMeasurementProvider.cpp +++ b/Tr/TrackTools/src/FTMeasurementProvider.cpp @@ -28,12 +28,15 @@ public: /// constructer FTMeasurementProvider(const std::string& type, - const std::string& name, - const IInterface* parent); + const std::string& name, + const IInterface* parent); StatusCode initialize() final; - LHCb::Measurement* measurement( const LHCb::LHCbID& id, bool localY=false ) const final; - LHCb::Measurement* measurement( const LHCb::LHCbID& id, const LHCb::ZTrajectory& refvector, bool localY=false) const final; + LHCb::Measurement* measurement( const LHCb::LHCbID& id, + bool localY=false ) const final; + LHCb::Measurement* measurement( const LHCb::LHCbID& id, + const LHCb::ZTrajectory& refvector, + bool localY=false) const final; inline LHCb::FTMeasurement* ftmeasurement( const LHCb::LHCbID& id ) const ; void handle ( const Incident& incident ) final; @@ -103,13 +106,10 @@ const FastClusterContainer<LHCb::FTLiteCluster,int>* FTMeasurementProvider::clus { /// If there is a new event, get the clusters and sort them according to their channel ID if( UNLIKELY(!m_clusters) ){ - m_clusters = getIfExists<FastClusterContainer<LHCb::FTLiteCluster,int> >( LHCb::FTLiteClusterLocation::Default ); - if(m_clusters){ //TODO: sort before putting clusters on the TES! - std::sort(m_clusters->begin(), m_clusters->end(), - [](const LHCb::FTLiteCluster& lhs, const LHCb::FTLiteCluster& rhs){ return lhs.channelID() < rhs.channelID(); }); - }else{ - error() << "Could not find FTLiteClusters at: " << LHCb::FTLiteClusterLocation::Default << endmsg; - } + m_clusters = getIfExists<FastClusterContainer<LHCb::FTLiteCluster,int> > + ( LHCb::FTLiteClusterLocation::Default ); + if(!m_clusters) error() << "Could not find FTLiteClusters at: " + << LHCb::FTLiteClusterLocation::Default << endmsg; } return m_clusters ; } @@ -123,8 +123,8 @@ LHCb::FTMeasurement* FTMeasurementProvider::ftmeasurement( const LHCb::LHCbID& i error() << "Not an FT measurement" << endmsg ; return nullptr; } - /// The clusters are sorted, so we can use a binary search (lower bound search) to find the element - /// corresponding to the channel ID + /// The clusters are sorted, so we can use a binary search (lower bound search) + /// to find the element corresponding to the channel ID const auto& c = *clusters(); auto itH = std::lower_bound( c.begin(), c.end(), id.ftID(), [](const LHCb::FTLiteCluster clus, const LHCb::FTChannelID id){ @@ -136,7 +136,8 @@ LHCb::FTMeasurement* FTMeasurementProvider::ftmeasurement( const LHCb::LHCbID& i //----------------------------------------------------------------------------- /// Return the measurement //----------------------------------------------------------------------------- -LHCb::Measurement* FTMeasurementProvider::measurement( const LHCb::LHCbID& id, bool /*localY*/ ) const { +LHCb::Measurement* FTMeasurementProvider::measurement( const LHCb::LHCbID& id, + bool /*localY*/ ) const { return ftmeasurement(id) ; } @@ -145,7 +146,8 @@ LHCb::Measurement* FTMeasurementProvider::measurement( const LHCb::LHCbID& id, b //----------------------------------------------------------------------------- LHCb::Measurement* FTMeasurementProvider::measurement( const LHCb::LHCbID& id, - const LHCb::ZTrajectory& /* reftraj */, bool /*localY*/ ) const { + const LHCb::ZTrajectory& /* reftraj */, + bool /*localY*/ ) const { // default implementation return ftmeasurement(id) ; } -- GitLab From 57ad224039d868bef585c8ae7e953b00a827f002 Mon Sep 17 00:00:00 2001 From: Jeroen van Tilburg <Jeroen.van.Tilburg@cern.ch> Date: Thu, 27 Oct 2016 20:38:25 +0200 Subject: [PATCH 07/68] Adapt to FT_61 geometry --- Pr/PrAlgorithms/src/PrFTHitManager.cpp | 16 ++++++------- Pr/PrMCTools/src/PrClustersResidual.cpp | 4 ++++ Tr/TrackFitEvent/src/FTMeasurement.cpp | 8 +++---- Tr/TrackTools/src/FTHitExpectation.cpp | 32 +++++++++++++------------ Tr/TrackTools/src/FTHitExpectation.h | 4 ++-- 5 files changed, 35 insertions(+), 29 deletions(-) diff --git a/Pr/PrAlgorithms/src/PrFTHitManager.cpp b/Pr/PrAlgorithms/src/PrFTHitManager.cpp index 8f4639ba2c..b02e774009 100644 --- a/Pr/PrAlgorithms/src/PrFTHitManager.cpp +++ b/Pr/PrAlgorithms/src/PrFTHitManager.cpp @@ -79,22 +79,22 @@ void PrFTHitManager::decodeData ( ) { FTLiteClusters* clusters = get<FTLiteClusters>( LHCb::FTLiteClusterLocation::Default ); if ( msgLevel( MSG::DEBUG) ) debug() << "Retrieved " << clusters->size() << " clusters" << endmsg; - const DeFTModule* module = nullptr; - unsigned int prevModuleID = 99999999; + const DeFTMat* mat = nullptr; + unsigned int prevMatID = 99999999; for ( auto clus : *clusters ) { - if( clus.channelID().uniqueModule() != prevModuleID ) { - module = m_ftDet->findModule( clus.channelID() ); - prevModuleID = module->elementID().uniqueModule(); + if( clus.channelID().uniqueMat() != prevMatID ) { + mat = m_ftDet->findMat( clus.channelID() ); + prevMatID = mat->elementID().uniqueMat(); } double fraction = clus.fraction(); LHCb::FTChannelID id = clus.channelID(); int lay = 4*(id.station()-1) + id.layer(); - int zone = int(module->isBottom()); + int zone = int(mat->isBottom()); int code = 2*lay + zone; - auto endPoints = module->endPoints(id, fraction); + auto endPoints = mat->endPoints(id, fraction); double invdy = 1./(endPoints.first.y()-endPoints.second.y()); double dxdy = (endPoints.first.x()-endPoints.second.x())*invdy; double dzdy = (endPoints.first.z()-endPoints.second.z())*invdy; @@ -103,7 +103,7 @@ void PrFTHitManager::decodeData ( ) { float yMin = std::min(endPoints.first.y(), endPoints.second.y()); float yMax = std::max(endPoints.first.y(), endPoints.second.y()); - float errX = 0.17; // TODO: this should be ~80 micron; get this from a tool + float errX = 0.170; // TODO: this should be ~80 micron; get this from a tool addHitInZone( code, LHCb::LHCbID( id ), x0, z0, dxdy, dzdy, yMin, yMax, errX , zone, lay ); if ( msgLevel(MSG::VERBOSE) ) verbose() << " .. hit " << id << " zone " << zone << " x " << x0 << endmsg; diff --git a/Pr/PrMCTools/src/PrClustersResidual.cpp b/Pr/PrMCTools/src/PrClustersResidual.cpp index faaf8592bc..16aea72a32 100644 --- a/Pr/PrMCTools/src/PrClustersResidual.cpp +++ b/Pr/PrMCTools/src/PrClustersResidual.cpp @@ -413,6 +413,7 @@ void PrClustersResidual::TrackStudy(){ //ChannelID of track hits std::vector<double> ChID_Fraction; std::vector<double> ChID_SipmCell; + std::vector<double> ChID_Mat; std::vector<double> ChID_Module; std::vector<double> ChID_Layer; std::vector<double> ChID_Quarter; @@ -471,6 +472,7 @@ void PrClustersResidual::TrackStudy(){ ChID_Fraction.push_back(liteCluster.fraction()); ChID_SipmCell.push_back(liteCluster.channelID().channel()); ChID_Module.push_back(liteCluster.channelID().module()); + ChID_Mat.push_back(liteCluster.channelID().mat()); ChID_Layer.push_back(liteCluster.channelID().layer()); ChID_Quarter.push_back(liteCluster.channelID().quarter()); ChID_Station.push_back(liteCluster.channelID().station()); @@ -540,6 +542,7 @@ void PrClustersResidual::TrackStudy(){ tuple->farray("ChID_Fraction",ChID_Fraction,"ChID",100); tuple->farray("ChID_SipmCell",ChID_SipmCell,"ChID",100); tuple->farray("ChID_Module",ChID_Module,"ChID",100); + tuple->farray("ChID_Mat",ChID_Mat,"ChID",100); tuple->farray("ChID_Layer",ChID_Layer,"ChID",100); tuple->farray("ChID_Quarter",ChID_Quarter,"ChID",100); tuple->farray("ChID_Station",ChID_Station,"ChID",100); @@ -1070,6 +1073,7 @@ void PrClustersResidual::ClusterResidual(){ tuple->column("ClusterChannelID",litecluster.channelID()); tuple->column("ClusterChannelIDSipmCell",litecluster.channelID().channel()); tuple->column("ClusterChannelIDSipmID",litecluster.channelID().sipm()); + tuple->column("ClusterChannelIDMat",litecluster.channelID().mat()); tuple->column("ClusterChannelIDStation",litecluster.channelID().station()); tuple->column("ClusterChannelIDModule",litecluster.channelID().module()); tuple->column("ClusterChannelLayer",litecluster.channelID().layer()); diff --git a/Tr/TrackFitEvent/src/FTMeasurement.cpp b/Tr/TrackFitEvent/src/FTMeasurement.cpp index 139b861bff..de28cfd7b4 100644 --- a/Tr/TrackFitEvent/src/FTMeasurement.cpp +++ b/Tr/TrackFitEvent/src/FTMeasurement.cpp @@ -18,12 +18,12 @@ using namespace LHCb; //----------------------------------------------------------------------------- void FTMeasurement::init( const DeFTDetector& geom ) { - const DeFTModule* ftModule = geom.findModule( m_cluster.channelID() ); - m_detectorElement = ftModule; + const DeFTMat* ftMat = geom.findMat( m_cluster.channelID() ); + m_detectorElement = ftMat; m_size = m_cluster.size(); m_errMeasure = 0.080; // + .030 * m_size; - m_trajectory = ftModule->trajectory(m_cluster.channelID(), m_cluster.fraction()); - m_z = ftModule->globalZ(); + m_trajectory = ftMat->trajectory(m_cluster.channelID(), m_cluster.fraction()); + m_z = ftMat->globalZ(); m_measure = 0. ; // JvT: I believe this is purely historical. Should remove it? } diff --git a/Tr/TrackTools/src/FTHitExpectation.cpp b/Tr/TrackTools/src/FTHitExpectation.cpp index aed5a2c5b3..88c41c2717 100644 --- a/Tr/TrackTools/src/FTHitExpectation.cpp +++ b/Tr/TrackTools/src/FTHitExpectation.cpp @@ -57,8 +57,8 @@ StatusCode FTHitExpectation::initialize() // Get all layers (need to know the z-plane of each layer) m_ftDet = getDet<DeFTDetector>(DeFTDetectorLocation::Default); - if ( m_ftDet -> version() < 60 ) - return Error("This version requires FTDet v6.0 or higher", StatusCode::FAILURE); + if ( m_ftDet -> version() < 61 ) + return Error("This version requires FTDet v6.1 or higher", StatusCode::FAILURE); return StatusCode::SUCCESS; } @@ -80,17 +80,16 @@ IHitExpectation::Info FTHitExpectation::expectation(const LHCb::Track& aTrack) c for( auto station : m_ftDet->stations() ) { for( auto layer : station->layers() ) { - const DeFTModule* module; + const DeFTMat* mat; Gaudi::XYZPoint intersectionPoint; - bool expectHit = findIntersectingModule(layer, aTrack, module, intersectionPoint); + bool expectHit = findIntersectingMat(layer, aTrack, mat, intersectionPoint); if( expectHit ) { ++(info.nExpected); // Check of this layer is present in the hits - auto itIter = std::find_if( ftHits.begin(), ftHits.end(), - [&module] (const LHCb::LHCbID& id) {return id.ftID().station() == module->stationID() && - id.ftID().layer() == module->layerID(); } ); + auto itIter = std::find_if( ftHits.begin(), ftHits.end(), [&mat] (const LHCb::LHCbID& id) + {return id.ftID().uniqueLayer() == mat->elementID().uniqueLayer(); } ); if (itIter != ftHits.end() ) ++info.nFound; } } @@ -100,8 +99,8 @@ IHitExpectation::Info FTHitExpectation::expectation(const LHCb::Track& aTrack) c } -bool FTHitExpectation::findIntersectingModule(const DeFTLayer* layer, const LHCb::Track& aTrack, - const DeFTModule*& module, Gaudi::XYZPoint& intersectionPoint) const { +bool FTHitExpectation::findIntersectingMat(const DeFTLayer* layer, const LHCb::Track& aTrack, + const DeFTMat*& mat, Gaudi::XYZPoint& intersectionPoint) const { // make a Line3D from the track double layerZ = layer->globalZ(); @@ -115,7 +114,7 @@ bool FTHitExpectation::findIntersectingModule(const DeFTLayer* layer, const LHCb intersectionPoint = intersection(aLine3D, layerPlane); // find the module that is hit - module = layer->findModule( intersectionPoint ); + const DeFTModule* module = layer->findModule( intersectionPoint ); if( module == nullptr ) return false; // find intersection point of track and plane of module @@ -125,8 +124,11 @@ bool FTHitExpectation::findIntersectingModule(const DeFTLayer* layer, const LHCb const Gaudi::Plane3D modulePlane = module->plane(); intersectionPoint = intersection(aLine3D, modulePlane); + // Find the corresponding mat + mat = module->findMat(intersectionPoint); + // check if intersection point is inside the fibres of the module - return module->isInsideSensitive( intersectionPoint ); + return (mat == nullptr ) ? false : mat->isInside( intersectionPoint ); } void FTHitExpectation::collect(const LHCb::Track& aTrack, @@ -135,15 +137,15 @@ void FTHitExpectation::collect(const LHCb::Track& aTrack, for( auto station : m_ftDet->stations() ) { for( auto layer : station->layers() ) { - const DeFTModule* module; + const DeFTMat* mat; Gaudi::XYZPoint intersectionPoint; - bool expectHit = findIntersectingModule(layer, aTrack, module, intersectionPoint); + bool expectHit = findIntersectingMat(layer, aTrack, mat, intersectionPoint); if( expectHit ) { // Find the channel that is closest - Gaudi::XYZPoint localP = module->geometry()->toLocal( intersectionPoint ); + Gaudi::XYZPoint localP = mat->geometry()->toLocal( intersectionPoint ); double frac; - LHCb::FTChannelID ftChan = module->calculateChannelAndFrac(localP.x(), frac); + LHCb::FTChannelID ftChan = mat->calculateChannelAndFrac(localP.x(), frac); // Add the channels // JvT: Without the fraction the bare FTChannelID is pretty useless... diff --git a/Tr/TrackTools/src/FTHitExpectation.h b/Tr/TrackTools/src/FTHitExpectation.h index b7f5c629a2..f7ae500130 100644 --- a/Tr/TrackTools/src/FTHitExpectation.h +++ b/Tr/TrackTools/src/FTHitExpectation.h @@ -71,8 +71,8 @@ public: private: - bool findIntersectingModule(const DeFTLayer* layer, const LHCb::Track& aTrack, - const DeFTModule*& module, Gaudi::XYZPoint& intersectionPoint) const ; + bool findIntersectingMat(const DeFTLayer* layer, const LHCb::Track& aTrack, + const DeFTMat*& mat, Gaudi::XYZPoint& intersectionPoint) const ; Gaudi::XYZPoint intersection(const Tf::Tsa::Line3D& line, const Gaudi::Plane3D& aPlane) const; -- GitLab From d6fe082b9b70aaf60a2ddd7dec36262321fce516 Mon Sep 17 00:00:00 2001 From: Jeroen van Tilburg <Jeroen.van.Tilburg@cern.ch> Date: Fri, 28 Oct 2016 21:39:59 +0200 Subject: [PATCH 08/68] Updated version in PrFTHitManager --- Pr/PrAlgorithms/src/PrFTHitManager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Pr/PrAlgorithms/src/PrFTHitManager.cpp b/Pr/PrAlgorithms/src/PrFTHitManager.cpp index b02e774009..38da87501a 100644 --- a/Pr/PrAlgorithms/src/PrFTHitManager.cpp +++ b/Pr/PrAlgorithms/src/PrFTHitManager.cpp @@ -35,8 +35,8 @@ void PrFTHitManager::buildGeometry ( ) { // Retrieve and initialize DeFT (no test: exception in case of failure) m_ftDet = getDet<DeFTDetector>( DeFTDetectorLocation::Default ); - if( m_ftDet->version() < 60 ) { - error() << "This version requires FTDet v6.0 or higher" << endmsg; + if( m_ftDet->version() < 61 ) { + error() << "This version requires FTDet v6.1 or higher" << endmsg; return; } -- GitLab From f02bbcf84c8f94f72d22a0f5ad98d31fdd20b7f9 Mon Sep 17 00:00:00 2001 From: Jeroen van Tilburg <Jeroen.van.Tilburg@cern.ch> Date: Wed, 2 Nov 2016 16:38:21 +0100 Subject: [PATCH 09/68] Changed debug statement --- Pr/PrAlgorithms/src/PrFTHitManager.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Pr/PrAlgorithms/src/PrFTHitManager.cpp b/Pr/PrAlgorithms/src/PrFTHitManager.cpp index 38da87501a..5f23bcc0db 100644 --- a/Pr/PrAlgorithms/src/PrFTHitManager.cpp +++ b/Pr/PrAlgorithms/src/PrFTHitManager.cpp @@ -78,7 +78,7 @@ void PrFTHitManager::decodeData ( ) { typedef FastClusterContainer<LHCb::FTLiteCluster,int> FTLiteClusters; FTLiteClusters* clusters = get<FTLiteClusters>( LHCb::FTLiteClusterLocation::Default ); if ( msgLevel( MSG::DEBUG) ) debug() << "Retrieved " << clusters->size() << " clusters" << endmsg; - + const DeFTMat* mat = nullptr; unsigned int prevMatID = 99999999; for ( auto clus : *clusters ) { @@ -106,7 +106,7 @@ void PrFTHitManager::decodeData ( ) { float errX = 0.170; // TODO: this should be ~80 micron; get this from a tool addHitInZone( code, LHCb::LHCbID( id ), x0, z0, dxdy, dzdy, yMin, yMax, errX , zone, lay ); if ( msgLevel(MSG::VERBOSE) ) - verbose() << " .. hit " << id << " zone " << zone << " x " << x0 << endmsg; + verbose() << " .. hit " << id << " code=" << code << " x=" << x0 << " z=" << z0 << endmsg; } for ( unsigned int lay = 0; nbZones() > lay ; ++lay ) { -- GitLab From 4ae38cc1701305bf937aba96a2a0c791bdd8762b Mon Sep 17 00:00:00 2001 From: Jeroen van Tilburg <Jeroen.van.Tilburg@cern.ch> Date: Tue, 15 Nov 2016 18:05:38 +0100 Subject: [PATCH 10/68] Adapted code to new Linker location --- Pr/PrMCTools/src/PrCheatedSciFiTracking.cpp | 4 ++-- Pr/PrMCTools/src/PrClustersResidual.cpp | 14 +++++++------- Pr/PrMCTools/src/PrPlotFTHits.cpp | 10 +++++----- Pr/PrMCTools/src/PrTStationDebugTool.cpp | 6 +++--- Tr/TrackFitEvent/src/FTMeasurement.cpp | 2 +- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/Pr/PrMCTools/src/PrCheatedSciFiTracking.cpp b/Pr/PrMCTools/src/PrCheatedSciFiTracking.cpp index 0adeff80b8..6c08a4010f 100644 --- a/Pr/PrMCTools/src/PrCheatedSciFiTracking.cpp +++ b/Pr/PrMCTools/src/PrCheatedSciFiTracking.cpp @@ -4,7 +4,7 @@ #include "Event/Track.h" #include "Event/StateParameters.h" #include "PrCheatedSciFiTracking.h" -#include "Event/FTCluster.h" +#include "Event/FTLiteCluster.h" #include "Linker/LinkedTo.h" #include "Event/MCTrackInfo.h" @@ -93,7 +93,7 @@ StatusCode PrCheatedSciFiTracking::finalize() { //========================================================================= void PrCheatedSciFiTracking::makeLHCbTracks ( LHCb::Tracks* result ) { - LinkedTo<LHCb::MCParticle, LHCb::FTCluster> myClusterLink ( evtSvc(), msgSvc(), LHCb::FTClusterLocation::Default ); + LinkedTo<LHCb::MCParticle> myClusterLink ( evtSvc(), msgSvc(), LHCb::FTLiteClusterLocation::Default ); LHCb::MCParticles* mcParts = getIfExists<LHCb::MCParticles> ( LHCb::MCParticleLocation::Default ); MCTrackInfo trackInfo( evtSvc(), msgSvc() ); diff --git a/Pr/PrMCTools/src/PrClustersResidual.cpp b/Pr/PrMCTools/src/PrClustersResidual.cpp index 16aea72a32..ab532fe688 100644 --- a/Pr/PrMCTools/src/PrClustersResidual.cpp +++ b/Pr/PrMCTools/src/PrClustersResidual.cpp @@ -123,8 +123,8 @@ void PrClustersResidual::Occupancy(){ const LHCb::MCHits* mcHitsPrev = getIfExists<LHCb::MCHits>("Prev/"+LHCb::MCHitLocation::FT);//"/Event/Prev/MC/FT/Hits" LinkedFrom<LHCb::MCHit,LHCb::MCParticle> myMCHitLink( evtSvc(), msgSvc(), LHCb::MCParticleLocation::Default + "2MC" + "FT" + "Hits" ); - LinkedTo<LHCb::MCParticle, LHCb::FTCluster> myClusterLink ( evtSvc(), msgSvc(), LHCb::FTClusterLocation::Default ); - LinkedTo<LHCb::MCHit, LHCb::FTCluster> myFTCluster2MCHitLink ( evtSvc(),msgSvc(), LHCb::FTClusterLocation::Default + "2MCHits"); + LinkedTo<LHCb::MCParticle> myClusterLink ( evtSvc(), msgSvc(), LHCb::FTLiteClusterLocation::Default ); + LinkedTo<LHCb::MCHit> myFTCluster2MCHitLink ( evtSvc(),msgSvc(), LHCb::FTLiteClusterLocation::Default + "2MCHits"); //"/Event/Prev/MC/FT/Hits" // mcHitsNext = getIfExists<MCHits>("Next/"+LHCb::MCHitLocation::FT); // mcHitsPrev = getIfExists<MCHits>("Prev/"+LHCb::MCHitLocation::FT); @@ -277,8 +277,8 @@ void PrClustersResidual::TrackStudy(){ LHCb::ODIN* odin=getIfExists<LHCb::ODIN>(LHCb::ODINLocation::Default); //Linker for the MCHit LinkedFrom<LHCb::MCHit,LHCb::MCParticle> myMCHitLink( evtSvc(), msgSvc(), LHCb::MCParticleLocation::Default + "2MC" + "FT" + "Hits" ); - LinkedTo<LHCb::MCParticle, LHCb::FTCluster> myClusterLink ( evtSvc(), msgSvc(), LHCb::FTClusterLocation::Default ); - LinkedTo<LHCb::MCHit, LHCb::FTCluster> myFTCluster2MCHitLink ( evtSvc(),msgSvc(), LHCb::FTClusterLocation::Default + "2MCHits"); + LinkedTo<LHCb::MCParticle> myClusterLink ( evtSvc(), msgSvc(), LHCb::FTLiteClusterLocation::Default ); + LinkedTo<LHCb::MCHit> myFTCluster2MCHitLink ( evtSvc(),msgSvc(), LHCb::FTLiteClusterLocation::Default + "2MCHits"); //Get the linker for the generation of the track to study (the one after the linker) //Get the McParticles LHCb::MCParticles* mcParts = getIfExists<LHCb::MCParticles> ( LHCb::MCParticleLocation::Default ); @@ -927,10 +927,10 @@ void PrClustersResidual::ClusterResidual(){ //LinkedTo<LHCb::MCParticle, LHCb::Track> myForwardLink ( evtSvc(), msgSvc(),LHCb::TrackLocation::Forward); //LinkedTo<LHCb::MCParticle, LHCb::Track> mySeedLink ( evtSvc(), msgSvc(),LHCb::TrackLocation::Seed); if(msgLevel(MSG::DEBUG)) debug()<<" Get ClusterLinker "<<endmsg; - LinkedTo<LHCb::MCParticle, LHCb::FTCluster> myClusterLink ( evtSvc(), msgSvc(), LHCb::FTClusterLocation::Default ); + LinkedTo<LHCb::MCParticle> myClusterLink ( evtSvc(), msgSvc(), LHCb::FTLiteClusterLocation::Default ); if(msgLevel(MSG::DEBUG)) debug()<<" Get Cluster to MCHit Linker "<<endmsg; - LinkedTo<LHCb::MCHit, LHCb::FTCluster> myFTCluster2MCHitLink ( evtSvc(),msgSvc(), LHCb::FTClusterLocation::Default + "2MCHits"); + LinkedTo<LHCb::MCHit> myFTCluster2MCHitLink ( evtSvc(),msgSvc(), LHCb::FTLiteClusterLocation::Default + "2MCHits"); MCTrackInfo trackInfo( evtSvc(), msgSvc() ); if(msgLevel(MSG::DEBUG)) debug()<<" Add MCHitAndTrackStudy "<<endmsg; Tuples::Tuple tuple = GaudiTupleAlg::nTuple("ClusterMCHitAndTrackStudy","Events"); @@ -1068,7 +1068,7 @@ void PrClustersResidual::ClusterResidual(){ //get Cluster associated to the Hit if(msgLevel(MSG::DEBUG)) debug()<<"Getting LiteCluster from PrHit"<<endmsg; LHCb::FTLiteCluster litecluster = getLiteCluster( (*iHit).id()); - tuple->column("ClusterSize",litecluster.size()); + tuple->column("ClusterSize",litecluster.isLarge()); tuple->column("ClusterFraction",litecluster.fraction()); tuple->column("ClusterChannelID",litecluster.channelID()); tuple->column("ClusterChannelIDSipmCell",litecluster.channelID().channel()); diff --git a/Pr/PrMCTools/src/PrPlotFTHits.cpp b/Pr/PrMCTools/src/PrPlotFTHits.cpp index bfb5b0da90..de6475f5ea 100644 --- a/Pr/PrMCTools/src/PrPlotFTHits.cpp +++ b/Pr/PrMCTools/src/PrPlotFTHits.cpp @@ -116,8 +116,8 @@ void PrPlotFTHits::plotOccupancy(){ //"/Event/Prev/MC/FT/Hits" LinkedFrom<LHCb::MCHit,LHCb::MCParticle> myMCHitLink( evtSvc(), msgSvc(), LHCb::MCParticleLocation::Default + "2MC" + "FT" + "Hits" ); - LinkedTo<LHCb::MCParticle, LHCb::FTCluster> myClusterLink ( evtSvc(), msgSvc(), LHCb::FTClusterLocation::Default ); - LinkedTo<LHCb::MCHit, LHCb::FTCluster> myFTCluster2MCHitLink ( evtSvc(),msgSvc(), LHCb::FTClusterLocation::Default + "2MCHits"); + LinkedTo<LHCb::MCParticle> myClusterLink ( evtSvc(), msgSvc(), LHCb::FTLiteClusterLocation::Default ); + LinkedTo<LHCb::MCHit> myFTCluster2MCHitLink ( evtSvc(),msgSvc(), LHCb::FTLiteClusterLocation::Default + "2MCHits"); //"/Event/Prev/MC/FT/Hits" char layerName[100]; char Title[100]; @@ -340,7 +340,7 @@ void PrPlotFTHits::plotHitEfficiency(){ // -- Link different track containers to MCParticles LinkedTo<LHCb::MCParticle, LHCb::Track> myForwardLink ( evtSvc(), msgSvc(),LHCb::TrackLocation::Forward); LinkedTo<LHCb::MCParticle, LHCb::Track> mySeedLink ( evtSvc(), msgSvc(),LHCb::TrackLocation::Seed); - LinkedTo<LHCb::MCParticle, LHCb::FTCluster> myClusterLink ( evtSvc(), msgSvc(), LHCb::FTClusterLocation::Default ); + LinkedTo<LHCb::MCParticle> myClusterLink ( evtSvc(), msgSvc(), LHCb::FTLiteClusterLocation::Default ); MCTrackInfo trackInfo( evtSvc(), msgSvc() ); // ----------------------------------------------------------------------------------- @@ -727,8 +727,8 @@ void PrPlotFTHits::plotMCHits () { // -- MC linking - LinkedTo<LHCb::MCHit, LHCb::FTCluster> myMCHitLink ( evtSvc(), msgSvc(), LHCb::FTClusterLocation::Default + "2MCHits"); - LinkedTo<LHCb::MCParticle, LHCb::FTCluster> myClusterLink ( evtSvc(), msgSvc(), LHCb::FTClusterLocation::Default ); + LinkedTo<LHCb::MCHit> myMCHitLink ( evtSvc(), msgSvc(), LHCb::FTLiteClusterLocation::Default + "2MCHits"); + LinkedTo<LHCb::MCParticle> myClusterLink ( evtSvc(), msgSvc(), LHCb::FTLiteClusterLocation::Default ); MCTrackInfo trackInfo( evtSvc(), msgSvc() ); diff --git a/Pr/PrMCTools/src/PrTStationDebugTool.cpp b/Pr/PrMCTools/src/PrTStationDebugTool.cpp index 8ec8b8f576..ccdcc199c4 100644 --- a/Pr/PrMCTools/src/PrTStationDebugTool.cpp +++ b/Pr/PrMCTools/src/PrTStationDebugTool.cpp @@ -5,7 +5,7 @@ #include "Linker/LinkedTo.h" #include "Kernel/LHCbID.h" #include "Event/OTTime.h" -#include "Event/FTCluster.h" +#include "Event/FTLiteCluster.h" #include "Event/MCParticle.h" // local @@ -51,7 +51,7 @@ bool PrTStationDebugTool::matchKey ( LHCb::LHCbID id, int key ) { part = oLink.next(); } } else if ( id.isFT() ) { - LinkedTo<LHCb::MCParticle> fLink( evtSvc(), msgSvc(), LHCb::FTClusterLocation::Default ); + LinkedTo<LHCb::MCParticle> fLink( evtSvc(), msgSvc(), LHCb::FTLiteClusterLocation::Default ); LHCb::FTChannelID idO = id.ftID(); LHCb::MCParticle* part = fLink.first( idO ); @@ -77,7 +77,7 @@ void PrTStationDebugTool::printKey( MsgStream& msg, LHCb::LHCbID id ) { part = oLink.next(); } } else if ( id.isFT() ) { - LinkedTo<LHCb::MCParticle> fLink( evtSvc(), msgSvc(), LHCb::FTClusterLocation::Default ); + LinkedTo<LHCb::MCParticle> fLink( evtSvc(), msgSvc(), LHCb::FTLiteClusterLocation::Default ); LHCb::FTChannelID idO = id.ftID(); LHCb::MCParticle* part = fLink.first( idO ); diff --git a/Tr/TrackFitEvent/src/FTMeasurement.cpp b/Tr/TrackFitEvent/src/FTMeasurement.cpp index de28cfd7b4..bb21204db0 100644 --- a/Tr/TrackFitEvent/src/FTMeasurement.cpp +++ b/Tr/TrackFitEvent/src/FTMeasurement.cpp @@ -20,7 +20,7 @@ void FTMeasurement::init( const DeFTDetector& geom ) { const DeFTMat* ftMat = geom.findMat( m_cluster.channelID() ); m_detectorElement = ftMat; - m_size = m_cluster.size(); + m_size = m_cluster.isLarge(); m_errMeasure = 0.080; // + .030 * m_size; m_trajectory = ftMat->trajectory(m_cluster.channelID(), m_cluster.fraction()); m_z = ftMat->globalZ(); -- GitLab From fae38bea01157e7d1bdcf3bb5076b9c997d0ea12 Mon Sep 17 00:00:00 2001 From: Jeroen van Tilburg <Jeroen.van.Tilburg@cern.ch> Date: Wed, 16 Nov 2016 18:20:45 +0100 Subject: [PATCH 11/68] Updated new linker location --- Pr/PrMCTools/src/PrLHCbID2MCParticle.cpp | 3 +-- Tr/TrackMCTools/src/LHCbIDsToMCHits.cpp | 4 ++-- Tr/TrackMCTools/src/LHCbIDsToMCHits.h | 3 +-- Tr/TrackMCTools/src/LHCbIDsToMCParticles.cpp | 4 ++-- Tr/TrackMCTools/src/LHCbIDsToMCParticles.h | 3 +-- 5 files changed, 7 insertions(+), 10 deletions(-) diff --git a/Pr/PrMCTools/src/PrLHCbID2MCParticle.cpp b/Pr/PrMCTools/src/PrLHCbID2MCParticle.cpp index a8838df294..96751f5d2e 100755 --- a/Pr/PrMCTools/src/PrLHCbID2MCParticle.cpp +++ b/Pr/PrMCTools/src/PrLHCbID2MCParticle.cpp @@ -8,7 +8,6 @@ #include "Event/VPCluster.h" #include "Event/STCluster.h" #include "Event/OTTime.h" -#include "Event/FTCluster.h" #include "Event/FTLiteCluster.h" // local @@ -164,7 +163,7 @@ StatusCode PrLHCbID2MCParticle::execute() { //== FT if ( exist<FastClusterContainer<LHCb::FTLiteCluster,int> >(LHCb::FTLiteClusterLocation::Default) ) { - LinkedTo<LHCb::MCParticle> ftLink( evtSvc(), msgSvc(),LHCb::FTClusterLocation::Default ); + LinkedTo<LHCb::MCParticle> ftLink( evtSvc(), msgSvc(),LHCb::FTLiteClusterLocation::Default ); if ( !ftLink.notFound() ) { m_detectorLink = &ftLink; typedef FastClusterContainer<LHCb::FTLiteCluster,int> FTLiteClusters; diff --git a/Tr/TrackMCTools/src/LHCbIDsToMCHits.cpp b/Tr/TrackMCTools/src/LHCbIDsToMCHits.cpp index bf50c89052..489f0ee166 100755 --- a/Tr/TrackMCTools/src/LHCbIDsToMCHits.cpp +++ b/Tr/TrackMCTools/src/LHCbIDsToMCHits.cpp @@ -10,7 +10,7 @@ #include "Event/VPCluster.h" #include "Event/OTTime.h" #include "Event/MuonCoord.h" -#include "Event/FTCluster.h" +#include "Event/FTLiteCluster.h" DECLARE_TOOL_FACTORY( LHCbIDsToMCHits ) @@ -219,7 +219,7 @@ void LHCbIDsToMCHits::linkFT(const LHCbID& lhcbid, LinkMap& output) const { if (!m_configuredFT){ m_configuredFT = true; - m_ftLinks = FTLinks( evtSvc(), msgSvc(),LHCb::FTClusterLocation::Default+m_endString); + m_ftLinks = FTLinks( evtSvc(), msgSvc(),LHCb::FTLiteClusterLocation::Default+m_endString); if (m_ftLinks.notFound()) { throw GaudiException("no FTLinker", "LHCbIDsToMCHits" , StatusCode::FAILURE); diff --git a/Tr/TrackMCTools/src/LHCbIDsToMCHits.h b/Tr/TrackMCTools/src/LHCbIDsToMCHits.h index 7d85e58a2e..59b049eb06 100755 --- a/Tr/TrackMCTools/src/LHCbIDsToMCHits.h +++ b/Tr/TrackMCTools/src/LHCbIDsToMCHits.h @@ -25,7 +25,6 @@ namespace LHCb{ class MuonCoord; class VPCluster; class UTCluster; - class FTCluster; } class LHCbIDsToMCHits: public GaudiTool, virtual public ILHCbIDsToMCHits, @@ -90,7 +89,7 @@ private: typedef LinkedTo<LHCb::MCHit,LHCb::VeloCluster> VeloLinks; typedef LinkedTo<LHCb::MCHit,LHCb::VPCluster> VPLinks; typedef LinkedTo<LHCb::MCHit,LHCb::MuonCoord> MuonLinks; - typedef LinkedTo<LHCb::MCHit,LHCb::FTCluster> FTLinks; + typedef LinkedTo<LHCb::MCHit> FTLinks; diff --git a/Tr/TrackMCTools/src/LHCbIDsToMCParticles.cpp b/Tr/TrackMCTools/src/LHCbIDsToMCParticles.cpp index f23be3735a..6793cb7c66 100755 --- a/Tr/TrackMCTools/src/LHCbIDsToMCParticles.cpp +++ b/Tr/TrackMCTools/src/LHCbIDsToMCParticles.cpp @@ -8,7 +8,7 @@ #include "Event/STCluster.h" #include "Event/VeloCluster.h" #include "Event/VPCluster.h" -#include "Event/FTCluster.h" +#include "Event/FTLiteCluster.h" #include "Event/OTTime.h" #include "Event/MuonCoord.h" @@ -237,7 +237,7 @@ StatusCode LHCbIDsToMCParticles::linkFT(const LHCbID& lhcbid, LinkMap& output) c if (!m_configuredFT){ m_configuredFT = true; m_ftLinks = FTLinks(evtSvc(), msgSvc(), - LHCb::FTClusterLocation::Default); + LHCb::FTLiteClusterLocation::Default); if (m_ftLinks.notFound()) { return Error("no FTLinker",StatusCode::FAILURE,10); } diff --git a/Tr/TrackMCTools/src/LHCbIDsToMCParticles.h b/Tr/TrackMCTools/src/LHCbIDsToMCParticles.h index 2ef15bb77f..e941842c82 100755 --- a/Tr/TrackMCTools/src/LHCbIDsToMCParticles.h +++ b/Tr/TrackMCTools/src/LHCbIDsToMCParticles.h @@ -24,7 +24,6 @@ namespace LHCb{ class VeloCluster; class MuonCoord; class VPCluster; - class FTCluster; } class LHCbIDsToMCParticles: public GaudiTool, virtual public ILHCbIDsToMCParticles, @@ -90,7 +89,7 @@ private: typedef LinkedTo<LHCb::MCParticle,LHCb::MuonCoord> MuonLinks; // -- upgrade typedef LinkedTo<LHCb::MCParticle,LHCb::VPCluster> VPLinks; - typedef LinkedTo<LHCb::MCParticle,LHCb::FTCluster> FTLinks; + typedef LinkedTo<LHCb::MCParticle> FTLinks; template<typename ID, typename LINKER> void linkToDetTruth(const ID& id, LINKER& aLinker, LinkMap& output ) const; -- GitLab From 5c59feafff943df33ab8220d9a7f8746f7dc311b Mon Sep 17 00:00:00 2001 From: Jeroen van Tilburg <Jeroen.van.Tilburg@cern.ch> Date: Wed, 14 Dec 2016 13:59:49 +0100 Subject: [PATCH 12/68] Updated release notes --- Pr/PrAlgorithms/doc/release.notes | 4 ++++ Pr/PrMCTools/doc/release.notes | 4 ++++ Tr/TrackFitEvent/doc/release.notes | 3 +++ Tr/TrackMCTools/doc/release.notes | 4 ++++ Tr/TrackTools/doc/release.notes | 4 ++++ 5 files changed, 19 insertions(+) diff --git a/Pr/PrAlgorithms/doc/release.notes b/Pr/PrAlgorithms/doc/release.notes index 8f2dbf7572..9b78e544d5 100644 --- a/Pr/PrAlgorithms/doc/release.notes +++ b/Pr/PrAlgorithms/doc/release.notes @@ -3,6 +3,10 @@ ! Responsible : Yasmine Amhis ! Purpose : Pattern reconstruction for the upgrade !----------------------------------------------------------------------------- + +! 2016-12-14 - Jeroen van Tilburg + - Adapt to new FT geometry and numbering scheme + 2016-04-18 Renato Quagliani - Fix warnings for unused variables 2016-04-18 Renato Quagliani diff --git a/Pr/PrMCTools/doc/release.notes b/Pr/PrMCTools/doc/release.notes index 93dd0ad667..429d61f803 100644 --- a/Pr/PrMCTools/doc/release.notes +++ b/Pr/PrMCTools/doc/release.notes @@ -4,6 +4,10 @@ ! Purpose : MC tools for pattern recognition for the Upgrade !----------------------------------------------------------------------------- +! 2016-12-14 - Jeroen van Tilburg + - Adapt to new FT geometry and numbering scheme + - Changed location of Linker tables. + !========================= PrMCTools v2r12 2016-01-28 ========================= ! 2016-01-21 Marco Cattaneo - Use std::abs instead of fabs for int argument, to silence clang warning diff --git a/Tr/TrackFitEvent/doc/release.notes b/Tr/TrackFitEvent/doc/release.notes index ebe90661e0..861836c30a 100755 --- a/Tr/TrackFitEvent/doc/release.notes +++ b/Tr/TrackFitEvent/doc/release.notes @@ -4,6 +4,9 @@ ! Purpose : Package for the tracking fitting-related classes !----------------------------------------------------------------------------- +! 2016-12-14 - Jeroen van Tilburg + - Adapt to new FT geometry and numbering scheme + !========================= TrackFitEvent v6r6 2016-01-28 ========================= ! 2015-12-05 - Gerhard Raven - reduce mention of 'static' and 'std::auto_ptr' diff --git a/Tr/TrackMCTools/doc/release.notes b/Tr/TrackMCTools/doc/release.notes index 4e14d1a888..d631e91644 100755 --- a/Tr/TrackMCTools/doc/release.notes +++ b/Tr/TrackMCTools/doc/release.notes @@ -4,6 +4,10 @@ ! Purpose : package for tracking tools accessing MC information !----------------------------------------------------------------------------- +! 2016-12-14 - Jeroen van Tilburg + - Adapt to new FT geometry and numbering scheme + - Changed location of Linker tables. + !========================= TrackMCTools v3r13 2016-03-18 ========================= ! 2016-02-08 - Adam Davis - Add more debugging tools for PatLongLivedTracking diff --git a/Tr/TrackTools/doc/release.notes b/Tr/TrackTools/doc/release.notes index 403a8e9a81..944ec15f97 100755 --- a/Tr/TrackTools/doc/release.notes +++ b/Tr/TrackTools/doc/release.notes @@ -4,6 +4,10 @@ ! Purpose : Package for tracking tools not accessing MC information !----------------------------------------------------------------------------- +! 2016-12-14 - Jeroen van Tilburg + - Adapt to new FT geometry and numbering scheme + - Changed location of Linker tables. + ! 2016-06-22 - David Hutchcroft - Added code to set the pT of the VELO only tracks with a sign based on the first strip in the first cluster rather than the track key (which was random). Also an option to reverse the sign -- GitLab From 918076c9b1d27b231d39c25dd6162deb56990509 Mon Sep 17 00:00:00 2001 From: Jeroen van Tilburg <Jeroen.van.Tilburg@cern.ch> Date: Thu, 15 Dec 2016 13:28:52 +0100 Subject: [PATCH 13/68] Fixing initialization with nullptr --- Pr/PrAlgorithms/src/PrFTHitManager.h | 2 +- Tr/TrackTools/src/FTHitExpectation.cpp | 3 +-- Tr/TrackTools/src/FTHitExpectation.h | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/Pr/PrAlgorithms/src/PrFTHitManager.h b/Pr/PrAlgorithms/src/PrFTHitManager.h index 8240041be7..7a84e409b0 100644 --- a/Pr/PrAlgorithms/src/PrFTHitManager.h +++ b/Pr/PrAlgorithms/src/PrFTHitManager.h @@ -37,6 +37,6 @@ public: protected: private: - DeFTDetector* m_ftDet; + DeFTDetector* m_ftDet = nullptr; }; #endif // PRFTHITMANAGER_H diff --git a/Tr/TrackTools/src/FTHitExpectation.cpp b/Tr/TrackTools/src/FTHitExpectation.cpp index 88c41c2717..03961af6c9 100644 --- a/Tr/TrackTools/src/FTHitExpectation.cpp +++ b/Tr/TrackTools/src/FTHitExpectation.cpp @@ -34,8 +34,7 @@ FTHitExpectation::FTHitExpectation(const std::string& type, const std::string& name, const IInterface* parent ): -THitExpectation(type, name, parent), - m_ftDet( NULL ) +THitExpectation(type, name, parent) { // constructor } diff --git a/Tr/TrackTools/src/FTHitExpectation.h b/Tr/TrackTools/src/FTHitExpectation.h index a4df836833..2ed2daac5d 100644 --- a/Tr/TrackTools/src/FTHitExpectation.h +++ b/Tr/TrackTools/src/FTHitExpectation.h @@ -76,7 +76,7 @@ private: Gaudi::XYZPoint intersection(const Tf::Tsa::Line3D& line, const Gaudi::Plane3D& aPlane) const; - DeFTDetector* m_ftDet; + DeFTDetector* m_ftDet = nullptr; }; -- GitLab From 23163654b723af9f3386a0e87829025dad4ac82e Mon Sep 17 00:00:00 2001 From: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Fri, 24 Feb 2017 14:20:29 +0000 Subject: [PATCH 14/68] Make sure sequence memers are reset --- .../RichFutureRecSys/ConfiguredRichReco.py | 9 +- Rich/RichRecTests/CMakeLists.txt | 46 ++++++++ Rich/RichRecTests/src/PhotonReco/main.cpp | 110 ++++++++++++++++++ 3 files changed, 160 insertions(+), 5 deletions(-) create mode 100644 Rich/RichRecTests/CMakeLists.txt create mode 100644 Rich/RichRecTests/src/PhotonReco/main.cpp diff --git a/Rich/RichFutureRecSys/python/RichFutureRecSys/ConfiguredRichReco.py b/Rich/RichFutureRecSys/python/RichFutureRecSys/ConfiguredRichReco.py index d4124f78e8..e99f4138a7 100644 --- a/Rich/RichFutureRecSys/python/RichFutureRecSys/ConfiguredRichReco.py +++ b/Rich/RichFutureRecSys/python/RichFutureRecSys/ConfiguredRichReco.py @@ -243,9 +243,6 @@ def RichRecoSequence( GroupName = "", # Optional name given to this group. if algprops["Detectors"][0] : pixname += "RICH1" if algprops["Detectors"][1] : pixname += "RICH2" - # The complete sequence - all = GaudiSequencer( "RichRecoSeq" + GroupName, MeasureTime = MeasureTime ) - # ================================================================== # RICH Pixel Treatment. Common to all track types and instanciations # of the RICH sequences. @@ -291,8 +288,9 @@ def RichRecoSequence( GroupName = "", # Optional name given to this group. pixels = GaudiSequencer( "RichPixels"+GroupName, MeasureTime = MeasureTime, Members = [ richCluster, richGloPoints, richLocPoints ] ) - # Add to final sequence - all.Members += [ pixels ] + # The complete sequence + all = GaudiSequencer( "RichRecoSeq" + GroupName, MeasureTime = MeasureTime ) + all.Members = [pixels] # Loop over tracks for tktype,trackLocation in inputTrackLocations.iteritems() : @@ -308,6 +306,7 @@ def RichRecoSequence( GroupName = "", # Optional name given to this group. # Sequencer for this track type tkSeq = GaudiSequencer( "Rich"+name+"Reco", MeasureTime = MeasureTime ) + tkSeq.Members = [ ] # make sure empty all.Members += [ tkSeq ] # ================================================================== diff --git a/Rich/RichRecTests/CMakeLists.txt b/Rich/RichRecTests/CMakeLists.txt new file mode 100644 index 0000000000..2c8215cc26 --- /dev/null +++ b/Rich/RichRecTests/CMakeLists.txt @@ -0,0 +1,46 @@ +################################################################################ +# Package: RichRecTests +################################################################################ +gaudi_subdir(RichRecTests v1r0) + +gaudi_depends_on_subdirs(Det/RichDet + GaudiKernel + Kernel/LHCbKernel + Kernel/LHCbMath + Kernel/VectorClass + Kernel/Vc + Rich/RichRecUtils) + +#find_package(vectorclass) +find_package(Boost) +find_package(GSL) +find_package(Eigen) +find_package(Vc) +find_package(ROOT COMPONENTS MathCore GenVector) + +message(STATUS "Using Vc ${Vc_INCLUDE_DIR} ${Vc_LIB_DIR}") +message(STATUS "Vc DEFINITIONS ${Vc_DEFINITIONS}") +message(STATUS "Vc COMPILE flags ${Vc_COMPILE_FLAGS}") +message(STATUS "Vc ARCHITECTURE flags ${Vc_ARCHITECTURE_FLAGS}") + +include_directories(SYSTEM ${Boost_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS} + ${EIGEN_INCLUDE_DIRS} ${Vc_INCLUDE_DIR}) + +if(GAUDI_BUILD_TESTS) + + gaudi_add_executable(RichPhotonRecoTest + src/PhotonReco/*.cpp + INCLUDE_DIRS ROOT Vc Eigen GSL VectorClass src + LINK_LIBRARIES LHCbMathLib GSL GaudiKernel) + target_link_libraries( RichPhotonRecoTest -lrt ) + + set_property(SOURCE src/RayTracing/main.cpp PROPERTY COMPILE_FLAGS " -Wno-ignored-attributes" ) + #set_property(SOURCE src/RayTracing/main.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -mfma -mavx2 -O3 -fabi-version=0 -fabi-compat-version=0 -ffp-contract=fast " ) + + gaudi_add_executable(RichRayTracingTest + src/RayTracing/*.cpp + INCLUDE_DIRS ROOT Vc Eigen GSL VectorClass src + LINK_LIBRARIES LHCbMathLib GSL GaudiKernel) + target_link_libraries( RichRayTracingTest "-lrt ${Vc_LIB_DIR}/libVc.a" ) + +endif() diff --git a/Rich/RichRecTests/src/PhotonReco/main.cpp b/Rich/RichRecTests/src/PhotonReco/main.cpp new file mode 100644 index 0000000000..01257568e5 --- /dev/null +++ b/Rich/RichRecTests/src/PhotonReco/main.cpp @@ -0,0 +1,110 @@ + +// Quartic Solver +#include "RichRecUtils/QuarticSolver.h" + +// STL +#include <random> +#include <vector> +#include <iostream> +#include <string> +#include <typeinfo> + +// Make an instance of the quartic solver +Rich::Rec::QuarticSolver qSolver; + +Gaudi::XYZPoint sphReflPoint; + +unsigned long long int time_diff( struct timespec *start, + struct timespec *stop ) +{ + if ((stop->tv_nsec - start->tv_nsec) < 0) { + return 1000000000ULL * (stop->tv_sec - start->tv_sec - 1) + + stop->tv_nsec - start->tv_nsec + 1000000000ULL; + } else { + return 1000000000ULL * (stop->tv_sec - start->tv_sec) + + stop->tv_nsec - start->tv_nsec; + } +} + +class Data +{ +public: + typedef std::vector<Data> Vector; +public: + Gaudi::XYZPoint emissPnt; + Gaudi::XYZPoint centOfCurv; + Gaudi::XYZPoint virtDetPoint; + double radius; +public: + Data() + { + // randomn generator + static std::default_random_engine gen; + // Distributions for each member + static std::uniform_real_distribution<double> r_emiss_x(-800,800), r_emiss_y(-600,600), r_emiss_z(10000,10500); + static std::uniform_real_distribution<double> r_coc_x(-3000,3000), r_coc_y(-20,20), r_coc_z(3300,3400); + static std::uniform_real_distribution<double> r_vdp_x(-3000,3000), r_vdp_y(-200,200), r_vdp_z(8100,8200); + static std::uniform_real_distribution<float> r_rad(8500,8600); + // setup data + emissPnt = Gaudi::XYZPoint( r_emiss_x(gen), r_emiss_y(gen), r_emiss_z(gen) ); + centOfCurv = Gaudi::XYZPoint( r_coc_x(gen), r_coc_y(gen), r_coc_z(gen) ); + virtDetPoint = Gaudi::XYZPoint( r_vdp_x(gen), r_vdp_y(gen), r_vdp_z(gen) ); + radius = r_rad(gen); + } +}; + +template< class TYPE > +inline void solve( const Data& data ) +{ + qSolver.solve<TYPE>( data.emissPnt, + data.centOfCurv, + data.virtDetPoint, + data.radius, + sphReflPoint ); +} + +template< class TYPE > +unsigned long long int __attribute__((noinline)) solve( const Data::Vector & dataV ) +{ + unsigned long long int best_dur{ 99999999999999999 }; + + timespec start, end; + + const unsigned int nTests = 1000; + for ( unsigned int i = 0; i < nTests; ++i ) + { + clock_gettime(CLOCK_MONOTONIC_RAW,&start); + // iterate over the data and solve it... + for ( const auto& data : dataV ) { solve<TYPE>(data); } + clock_gettime(CLOCK_MONOTONIC_RAW,&end); + const auto duration = time_diff(&start,&end); + if ( duration < best_dur ) { best_dur = duration; } + } + + return best_dur ; +} + +int main ( int /*argc*/, char** /*argv*/ ) +{ + const unsigned int nPhotons = 1e4; + + Data::Vector dataV; + dataV.reserve( nPhotons ); + // Construct the data to work on + std::cout << "Creating " << nPhotons << " random photons ..." << std::endl; + for ( unsigned int i = 0; i < nPhotons; ++i ) { dataV.push_back( Data() ); } + + // run the solver for floats + auto fTime = solve<float>( dataV ); + std::cout << "Float " << fTime << std::endl; + + // run the solver for doubles + auto dTime = solve<double>( dataV ); + std::cout << "Double " << dTime << std::endl; + + // make sure we are not optimized away + asm volatile ("" : "+x"(fTime)); + asm volatile ("" : "+x"(dTime)); + + return 0; +} -- GitLab From ce10e2492bfb317abfbaa29bf14f137337bf89d4 Mon Sep 17 00:00:00 2001 From: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Fri, 24 Feb 2017 14:21:22 +0000 Subject: [PATCH 15/68] Protect debug statement --- Rich/RichFutureRecTrackAlgorithms/src/RichBaseTrSegMaker.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Rich/RichFutureRecTrackAlgorithms/src/RichBaseTrSegMaker.cpp b/Rich/RichFutureRecTrackAlgorithms/src/RichBaseTrSegMaker.cpp index 14b9006693..65b1025f2b 100755 --- a/Rich/RichFutureRecTrackAlgorithms/src/RichBaseTrSegMaker.cpp +++ b/Rich/RichFutureRecTrackAlgorithms/src/RichBaseTrSegMaker.cpp @@ -40,7 +40,7 @@ StatusCode BaseTrSegMaker::initialize() if ( !usedRads(Rich::Aerogel) ) { - debug() << "Track segments for Aerogel are disabled" << endmsg; + _ri_debug << "Track segments for Aerogel are disabled" << endmsg; //Warning("Track segments for Aerogel are disabled",StatusCode::SUCCESS).ignore(); //made into debug as it is still too verbose as a warning } -- GitLab From 04780b1e1a7e8066002b4db2985ab31520dbd12e Mon Sep 17 00:00:00 2001 From: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Fri, 24 Feb 2017 14:21:50 +0000 Subject: [PATCH 16/68] Move test applications to Rich/RichRecTests --- Rich/RichRecPhotonTools/CMakeLists.txt | 6 ------ 1 file changed, 6 deletions(-) diff --git a/Rich/RichRecPhotonTools/CMakeLists.txt b/Rich/RichRecPhotonTools/CMakeLists.txt index c551830b1f..231f8c58a3 100644 --- a/Rich/RichRecPhotonTools/CMakeLists.txt +++ b/Rich/RichRecPhotonTools/CMakeLists.txt @@ -24,9 +24,3 @@ gaudi_add_module(RichRecPhotonTools INCLUDE_DIRS Eigen Boost GSL VectorClass src LINK_LIBRARIES Boost GSL RichDetLib GaudiKernel LHCbKernel LHCbMathLib RichKernelLib RichRecBase) -if(GAUDI_BUILD_TESTS) - gaudi_add_executable(RichPhotonRecoTest - src/application/PhotonReco/*.cpp - INCLUDE_DIRS ROOT Eigen GSL VectorClass src - LINK_LIBRARIES LHCbMathLib GSL GaudiKernel ROOT) -endif() -- GitLab From 59a5f1a007dc30496aad5023dc7d6d35e736a9c1 Mon Sep 17 00:00:00 2001 From: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Fri, 24 Feb 2017 14:22:21 +0000 Subject: [PATCH 17/68] Add ray tracing test application --- Rich/RichRecTests/src/RayTracing/main.cpp | 252 ++++++++++++++++++++++ 1 file changed, 252 insertions(+) create mode 100644 Rich/RichRecTests/src/RayTracing/main.cpp diff --git a/Rich/RichRecTests/src/RayTracing/main.cpp b/Rich/RichRecTests/src/RayTracing/main.cpp new file mode 100644 index 0000000000..7b109c29e2 --- /dev/null +++ b/Rich/RichRecTests/src/RayTracing/main.cpp @@ -0,0 +1,252 @@ + +// STL +#include <random> +#include <vector> +#include <iostream> +#include <string> +#include <typeinfo> + +// LHCbMath +#include "LHCbMath/EigenTypes.h" +#include "LHCbMath/VectorClassTypes.h" + +// Rich Utils +#include "RichUtils/RichRayTracingUtils.h" +#include "RichUtils/ZipRange.h" + +#include <Vc/Vc> + +unsigned long long int time_diff( struct timespec *start, + struct timespec *stop ) +{ + if ((stop->tv_nsec - start->tv_nsec) < 0) { + return 1000000000ULL * (stop->tv_sec - start->tv_sec - 1) + + stop->tv_nsec - start->tv_nsec + 1000000000ULL; + } else { + return 1000000000ULL * (stop->tv_sec - start->tv_sec) + + stop->tv_nsec - start->tv_nsec; + } +} + +// randomn generator +static std::default_random_engine gen; +// Distributions for each member +static std::uniform_real_distribution<double> p_x(-800,800), p_y(-600,600), p_z(10000,10500); +static std::uniform_real_distribution<double> d_x(-0.2,0.2), d_y(-0.1,0.1), d_z(0.95,0.99); +static std::uniform_real_distribution<double> c_x(3100,3200), c_y(10,15), c_z(3200,3300); +static std::uniform_real_distribution<double> r_rad(8500,8600); +static std::uniform_real_distribution<double> p0(-0.002,0.002), p1(-0.2,0.2), p2(0.97,0.99), p3(-1300,1300); + +template < typename POINT, typename VECTOR, typename PLANE, typename FTYPE > +class Data +{ +public: + typedef std::vector<Data> Vector; +public: + POINT position; + VECTOR direction; + POINT CoC; + PLANE plane; + FTYPE radius{0}; +public: + template< typename INDATA > + Data( const INDATA & ind ) + : position(ind.position), + direction(ind.direction), + CoC(ind.CoC), + plane(ind.plane), + radius(ind.radius) { } + Data( ) + : position ( p_x(gen), p_y(gen), p_z(gen) ), + direction ( d_x(gen), d_y(gen), d_z(gen) ), + CoC ( c_x(gen), c_y(gen), c_z(gen) ), + plane ( p0(gen), p1(gen), p2(gen), p3(gen) ), + radius ( r_rad(gen) ) { } +}; + +template < typename DATA > +inline void trace( DATA & dataV ) +{ + using namespace Rich::RayTracingUtils; + for ( auto & data : dataV ) + { + reflectSpherical( data.position, data.direction, data.CoC, data.radius ); + } +} + + +template < typename DATA > +unsigned long long int __attribute__((noinline)) rayTrace( const DATA & in_dataV ) +{ + timespec start, end; + + unsigned long long int best_dur{ 99999999999999999 }; + + const unsigned int nTests = 10000; + for ( unsigned int i = 0; i < nTests; ++i ) + { + auto dataV = in_dataV; // copy data, as it will be modified + clock_gettime(CLOCK_MONOTONIC_RAW,&start); + trace( dataV ); + clock_gettime(CLOCK_MONOTONIC_RAW,&end); + const auto duration = time_diff(&start,&end); + if ( duration < best_dur ) { best_dur = duration; } + } + + return best_dur ; +} + +int main ( int /*argc*/, char** /*argv*/ ) +{ + + const unsigned int nPhotons = 96 * 1e2; + std::cout << "Creating " << nPhotons << " random photons ..." << std::endl; + + // Vc + using VcXYZPointD = ROOT::Math::PositionVector3D<ROOT::Math::Cartesian3D<Vc::double_v>,ROOT::Math::DefaultCoordinateSystemTag>; + using VcXYZVectorD = ROOT::Math::DisplacementVector3D<ROOT::Math::Cartesian3D<Vc::double_v>,ROOT::Math::DefaultCoordinateSystemTag>; + using VcXYZPointF = ROOT::Math::PositionVector3D<ROOT::Math::Cartesian3D<Vc::float_v>,ROOT::Math::DefaultCoordinateSystemTag>; + using VcXYZVectorF = ROOT::Math::DisplacementVector3D<ROOT::Math::Cartesian3D<Vc::float_v>,ROOT::Math::DefaultCoordinateSystemTag>; + + //if ( false ) + { + + // Data in 'ROOT' SMatrix double format + Data<Gaudi::XYZPoint,Gaudi::XYZVector,Gaudi::Plane3D,Gaudi::XYZVector::Scalar>::Vector root_dataV( nPhotons ); + auto resROOT = rayTrace( root_dataV ); + std::cout << "ROOT double " << resROOT << std::endl; + + // Same data in Eigen double format + Data<LHCb::Math::Eigen::XYZPoint<double>,LHCb::Math::Eigen::XYZVector<double>,double>::Vector eigen_dataV( nPhotons ); + auto resEIGEN = rayTrace( eigen_dataV ); + std::cout << "Eigen double " << resEIGEN << " speedup " << (float)resROOT/(float)resEIGEN << std::endl; + + // _mm256_zeroupper(); + + // Same data in VectorClass double format + Data<LHCb::Math::VectorClass::XYZPoint<double>,LHCb::Math::VectorClass::XYZVector<double>,double>::Vector vclass_dataV( nPhotons ); + auto resVClass = rayTrace( vclass_dataV ); + std::cout << "VectorClass double " << resVClass << " speedup " << (float)resROOT/(float)resVClass << std::endl; + + // Vc float + Data<VcXYZPointD,VcXYZVectorD,Vc::double_v>::Vector VC_dataV( nPhotons / Vc::double_v::Size ); + auto resVC = rayTrace( VC_dataV ); + std::cout << "Vc double " << resVC << " speedup " << (float)resROOT/(float)resVC << std::endl; + + // make sure we are not optimized away + asm volatile ("" : "+x"(resROOT)); + asm volatile ("" : "+x"(resEIGEN)); + asm volatile ("" : "+x"(resVClass)); + asm volatile ("" : "+x"(resVC)); + + } + + //if ( false ) + { + + // Data in 'ROOT' SMatrix double format + Data<Gaudi::XYZPointF,Gaudi::XYZVectorF,Gaudi::Plane3DF,Gaudi::XYZVectorF::Scalar>::Vector root_dataV( nPhotons ); + auto resROOT = rayTrace( root_dataV ); + std::cout << "ROOT float " << resROOT << std::endl; + + // Same data in Eigen double format + Data<LHCb::Math::Eigen::XYZPoint<float>,LHCb::Math::Eigen::XYZVector<float>,float>::Vector eigen_dataV( nPhotons ); + auto resEIGEN = rayTrace( eigen_dataV ); + std::cout << "Eigen float " << resEIGEN << " speedup " << (float)resROOT/(float)resEIGEN << std::endl; + + // Same data in VectorClass double format + Data<LHCb::Math::VectorClass::XYZPoint<float>,LHCb::Math::VectorClass::XYZVector<float>,float>::Vector vclass_dataV( nPhotons ); + auto resVClass = rayTrace( vclass_dataV ); + std::cout << "VectorClass float " << resVClass << " speedup " << (float)resROOT/(float)resVClass << std::endl; + + // Vc float + Data<VcXYZPointF,VcXYZVectorF,Vc::float_v>::Vector VC_dataV( nPhotons / Vc::float_v::Size ); + auto resVC = rayTrace( VC_dataV ); + std::cout << "Vc float " << resVC << " speedup " << (float)resROOT/(float)resVC << std::endl; + + // make sure we are not optimized away + asm volatile ("" : "+x"(resROOT)); + asm volatile ("" : "+x"(resEIGEN)); + asm volatile ("" : "+x"(resVClass)); + asm volatile ("" : "+x"(resVC)); + + } + + // Basic checks + if ( false ) + { + + std::vector< Vc::float_v > a = { 1, 2, 3, 4, 5, 6, 7, 8 }; + std::vector< Vc::float_v > b = { 1, 2, 3, 4, 5, 6, 7, 8 }; + + std::cout << "Size " << a.size() << " " << Vc::float_v::Size << std::endl; + + for ( unsigned int i = 0; i < (a.size()/Vc::float_v::Size); ++i ) + { + a[i] += b[i]; + std::cout << "Filling " << i << " " << a[i] << " " << b[i] << std::endl; + } + + for ( unsigned int i = 0; i < a.size(); ++i ) + { + std::cout << "Reading " << i << " " << a[i] << " " << b[i] << std::endl; + } + + } + + + // VC example + if ( false ) + { + + using Vc::float_v; + //! [includes] + + //! [memory allocation] + + // allocate memory for our initial x and y coordinates. Note that you can also put it into a + // normal float C-array but that you then must ensure alignment to Vc::VectorAlignment! + Vc::Memory<float_v, 100> x_mem; + Vc::Memory<float_v, 100> y_mem; + Vc::Memory<float_v, 100> r_mem; + Vc::Memory<float_v, 100> phi_mem; + //! [memory allocation] + + //! [random init] + // fill the memory with values from -1.f to 1.f + std::cout << "vectorsCount = " << x_mem.vectorsCount() << std::endl; + for (size_t i = 0; i < x_mem.vectorsCount(); ++i) + { + x_mem.vector(i) = float_v::Random() * 2.f - 1.f; + y_mem.vector(i) = float_v::Random() * 2.f - 1.f; + } + //! [random init] + + //! [conversion] + // calculate the polar coordinates for all coordinates and overwrite the euclidian coordinates + // with the result + for (size_t i = 0; i < x_mem.vectorsCount(); ++i) + { + const float_v x = x_mem.vector(i); + const float_v y = y_mem.vector(i); + + r_mem.vector(i) = Vc::sqrt(x * x + y * y); + float_v phi = Vc::atan2(y, x) * 57.295780181884765625f; // 180/pi + phi(phi < 0.f) += 360.f; + phi_mem.vector(i) = phi; + } + //! [conversion] + + //! [output] + // print the results + std::cout << "entriesCount = " << x_mem.entriesCount() << std::endl; + for (size_t i = 0; i < x_mem.entriesCount(); ++i) { + std::cout << std::setw(3) << i << ": "; + std::cout << std::setw(10) << x_mem[i] << ", " << std::setw(10) << y_mem[i] << " -> "; + std::cout << std::setw(10) << r_mem[i] << ", " << std::setw(10) << phi_mem[i] << '\n'; + } + + } + + return 0; +} -- GitLab From 9e09fcf9d8d2ac60a6767894f96b689967c93d53 Mon Sep 17 00:00:00 2001 From: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Fri, 24 Feb 2017 14:22:49 +0000 Subject: [PATCH 18/68] Minor updates to QuarticSolver.h --- .../RichRecUtils/RichRecUtils/QuarticSolver.h | 197 +++++++++--------- 1 file changed, 95 insertions(+), 102 deletions(-) diff --git a/Rich/RichRecUtils/RichRecUtils/QuarticSolver.h b/Rich/RichRecUtils/RichRecUtils/QuarticSolver.h index 4fbabe905e..067801e216 100755 --- a/Rich/RichRecUtils/RichRecUtils/QuarticSolver.h +++ b/Rich/RichRecUtils/RichRecUtils/QuarticSolver.h @@ -7,8 +7,7 @@ */ //---------------------------------------------------------------------- -#ifndef RICHRECPHOTONTOOLS_QuarticSolver_H -#define RICHRECPHOTONTOOLS_QuarticSolver_H 1 +#pragma once // Gaudi #include "GaudiKernel/Kernel.h" @@ -52,100 +51,6 @@ namespace Rich class QuarticSolver final { - public: - - // Use eigen types - typedef LHCb::Math::Eigen::XYZPoint Point; ///< Point type - typedef LHCb::Math::Eigen::XYZVector Vector; ///< vector type - - public: - - /** Solves the characteristic quartic equation for the RICH optical system. - * - * See note LHCB/98-040 RICH section 3 for more details - * - * @param emissionPoint Assumed photon emission point on track - * @param CoC Spherical mirror centre of curvature - * @param virtDetPoint Virtual detection point - * @param radius Spherical mirror radius of curvature - * @param sphReflPoint The reconstructed reflection pont on the spherical mirror - * - * @return boolean indicating status of the quartic solution - * @retval true Calculation was successful. sphReflPoint is valid. - * @retval false Calculation failed. sphReflPoint is not valid. - */ - template< class TYPE > - inline void solve( const Gaudi::XYZPoint& emissionPoint, - const Gaudi::XYZPoint& CoC, - const Gaudi::XYZPoint& virtDetPoint, - const TYPE radius, - Gaudi::XYZPoint& sphReflPoint ) const - { - - // typedefs vectorised types - typedef Eigen::Matrix< TYPE , 3 , 1 > Eigen3Vector; - using Vec4x = - typename std::conditional<std::is_same<TYPE,float>::value,Vec4f,Vec4d>::type; - - // vector from mirror centre of curvature to assumed emission point - const Vector evec( emissionPoint - CoC ); - const TYPE e2 = evec.dot(evec); - - // vector from mirror centre of curvature to virtual detection point - const Vector dvec( virtDetPoint - CoC ); - const TYPE d2 = dvec.dot(dvec); - - // various quantities needed to create quartic equation - // see LHCB/98-040 section 3, equation 3 - const auto ed2 = e2 * d2; - const TYPE cosgamma2 = ( ed2 > 0 ? std::pow(evec.dot(dvec),2)/ed2 : 1.0 ); - // vectorise 4 square roots into 1 - const auto tmp_sqrt = sqrt( Vec4x( e2, d2, - cosgamma2 < 1.0 ? 1.0-cosgamma2 : 0.0, - cosgamma2 ) ); - const auto e = tmp_sqrt[0]; - const auto d = tmp_sqrt[1]; - const auto singamma = tmp_sqrt[2]; - const auto cosgamma = tmp_sqrt[3]; - - const auto dx = d * cosgamma; - const auto dy = d * singamma; - const auto r2 = radius * radius; - const auto dy2 = dy * dy; - const auto edx = e + dx; - - // Fill array for quartic equation - const auto a0 = 4.0 * ed2; - const auto inv_a0 = ( a0 > 0 ? 1.0 / a0 : std::numeric_limits<TYPE>::max() ); - const auto dyrad2 = 2.0 * dy * radius; - const auto a1 = - ( 2.0 * dyrad2 * e2 ) * inv_a0; - const auto a2 = ( (dy2 * r2) + ( edx * edx * r2 ) - a0 ) * inv_a0; - const auto a3 = ( dyrad2 * e * (e-dx) ) * inv_a0; - const auto a4 = ( ( e2 - r2 ) * dy2 ) * inv_a0; - - // use simplified RICH version of quartic solver - const auto sinbeta = solve_quartic_RICH<TYPE>( a1, // a - a2, // b - a3, // c - a4 // d - ); - - // (normalised) normal vector to reflection plane - auto n = evec.cross3(dvec); - n /= std::sqrt( n.dot(n) ); - - // construct rotation transformation - // Set vector magnitude to radius - // rotate vector and update reflection point - const Eigen::AngleAxis<TYPE> angleaxis( vdt::fast_asinf(sinbeta), - Eigen3Vector(n[0],n[1],n[2]) ); - sphReflPoint = ( CoC + - Gaudi::XYZVector( angleaxis * - Eigen3Vector(evec[0],evec[1],evec[2]) * - ( radius / e ) ) ); - - } - private: /// The cube root implementaton to use @@ -169,10 +74,10 @@ namespace Rich */ //---------------------------------------------------------------------- template < class TYPE > - inline TYPE solve_quartic_RICH ( const TYPE& a, - const TYPE& b, - const TYPE& c, - const TYPE& d ) const + inline TYPE solve_quartic_RICH ( const TYPE a, + const TYPE b, + const TYPE c, + const TYPE d ) const { constexpr const TYPE r4 = 1.0 / 4.0; @@ -237,9 +142,97 @@ namespace Rich res ); } + public: + + /** Solves the characteristic quartic equation for the RICH optical system. + * + * See note LHCB/98-040 RICH section 3 for more details + * + * @param emissionPoint Assumed photon emission point on track + * @param CoC Spherical mirror centre of curvature + * @param virtDetPoint Virtual detection point + * @param radius Spherical mirror radius of curvature + * @param sphReflPoint The reconstructed reflection pont on the spherical mirror + * + * @return boolean indicating status of the quartic solution + * @retval true Calculation was successful. sphReflPoint is valid. + * @retval false Calculation failed. sphReflPoint is not valid. + */ + template< class TYPE > + inline void solve( const Gaudi::XYZPoint& emissionPoint, + const Gaudi::XYZPoint& CoC, + const Gaudi::XYZPoint& virtDetPoint, + const TYPE radius, + Gaudi::XYZPoint& sphReflPoint ) const + { + + // typedefs vectorised types + using Eigen3Vector = Eigen::Matrix< TYPE , 3 , 1 >; + using Vector = LHCb::Math::Eigen::XYZVector<TYPE>; + using Point = LHCb::Math::Eigen::XYZPoint<TYPE>; + using Vec4x = + typename std::conditional<std::is_same<TYPE,float>::value,Vec4f,Vec4d>::type; + + // vector from mirror centre of curvature to assumed emission point + const Vector evec( emissionPoint - CoC ); + const TYPE e2 = evec.dot(evec); + + // vector from mirror centre of curvature to virtual detection point + const Vector dvec( virtDetPoint - CoC ); + const TYPE d2 = dvec.dot(dvec); + + // various quantities needed to create quartic equation + // see LHCB/98-040 section 3, equation 3 + const auto ed2 = e2 * d2; + const TYPE cosgamma2 = ( ed2 > 0 ? std::pow(evec.dot(dvec),2)/ed2 : 1.0 ); + // vectorise 4 square roots into 1 + const auto tmp_sqrt = sqrt( Vec4x( e2, d2, + cosgamma2 < 1.0 ? 1.0-cosgamma2 : 0.0, + cosgamma2 ) ); + const auto e = tmp_sqrt[0]; + const auto d = tmp_sqrt[1]; + const auto singamma = tmp_sqrt[2]; + const auto cosgamma = tmp_sqrt[3]; + + const auto dx = d * cosgamma; + const auto dy = d * singamma; + const auto r2 = radius * radius; + const auto dy2 = dy * dy; + const auto edx = e + dx; + + // Fill array for quartic equation + const auto a0 = 4.0 * ed2; + const auto inv_a0 = ( a0 > 0 ? 1.0 / a0 : std::numeric_limits<TYPE>::max() ); + const auto dyrad2 = 2.0 * dy * radius; + const auto a1 = - ( 2.0 * dyrad2 * e2 ) * inv_a0; + const auto a2 = ( (dy2 * r2) + ( edx * edx * r2 ) - a0 ) * inv_a0; + const auto a3 = ( dyrad2 * e * (e-dx) ) * inv_a0; + const auto a4 = ( ( e2 - r2 ) * dy2 ) * inv_a0; + + // use simplified RICH version of quartic solver + const auto sinbeta = solve_quartic_RICH<TYPE>( a1, // a + a2, // b + a3, // c + a4 // d + ); + + // (normalised) normal vector to reflection plane + auto n = evec.cross3(dvec); + n /= std::sqrt( n.dot(n) ); + + // construct rotation transformation + // Set vector magnitude to radius + // rotate vector and update reflection point + const Eigen::AngleAxis<TYPE> angleaxis( vdt::fast_asinf(sinbeta), + Eigen3Vector(n[0],n[1],n[2]) ); + sphReflPoint = ( CoC + + Gaudi::XYZVector( angleaxis * + Eigen3Vector(evec[0],evec[1],evec[2]) * + ( radius / e ) ) ); + + } + }; } } - -#endif // RICHRECPHOTONTOOLS_QuarticSolver_H -- GitLab From 06c90270d2591bf86dc63fbd17f9fc1223ffb0a1 Mon Sep 17 00:00:00 2001 From: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Fri, 24 Feb 2017 14:23:19 +0000 Subject: [PATCH 19/68] update scripts --- Rich/RichFutureRecSys/examples/Brunel.py | 6 +++--- Rich/RichFutureRecSys/examples/RichFuture.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Rich/RichFutureRecSys/examples/Brunel.py b/Rich/RichFutureRecSys/examples/Brunel.py index a522b3d505..afccb289d4 100644 --- a/Rich/RichFutureRecSys/examples/Brunel.py +++ b/Rich/RichFutureRecSys/examples/Brunel.py @@ -45,13 +45,13 @@ Brunel().MCCheckSequence = richs+["PROTO"] ############################################################################# # Timestamps in messages -LHCbApp().TimeStamp = True +#LHCbApp().TimeStamp = True Brunel().OutputType = 'None' importOptions("$APPCONFIGOPTS/Persistency/Compression-ZLIB-1.py") -Brunel().EvtMax = 5000 -Brunel().PrintFreq = 500 +Brunel().EvtMax = 500 +Brunel().PrintFreq = 100 #Brunel().Histograms = "Expert" diff --git a/Rich/RichFutureRecSys/examples/RichFuture.py b/Rich/RichFutureRecSys/examples/RichFuture.py index 0186612021..43d45a745e 100644 --- a/Rich/RichFutureRecSys/examples/RichFuture.py +++ b/Rich/RichFutureRecSys/examples/RichFuture.py @@ -94,7 +94,7 @@ RichCheck = RichRecCheckers( inputTrackLocations = tkLocs, # The final sequence to run all = GaudiSequencer( "All", Members = [ fetcher, odinDecode, richDecode, tkUnpack, tkFilt, RichRec ] ) -all.Members += [ RichMoni ] +#all.Members += [ RichMoni ] #all.Members += [ mcPUnpack, RichCheck ] all.MeasureTime = True -- GitLab From f83255de2ce63f0d2c568e07ee5e9a3b1e6e5b46 Mon Sep 17 00:00:00 2001 From: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Fri, 24 Feb 2017 14:23:40 +0000 Subject: [PATCH 20/68] Fix doxygen comment --- .../src/RichTrackFunctionalCherenkovResolutions.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Rich/RichFutureRecTrackAlgorithms/src/RichTrackFunctionalCherenkovResolutions.h b/Rich/RichFutureRecTrackAlgorithms/src/RichTrackFunctionalCherenkovResolutions.h index c8fc19ba0f..c5f3e88bef 100644 --- a/Rich/RichFutureRecTrackAlgorithms/src/RichTrackFunctionalCherenkovResolutions.h +++ b/Rich/RichFutureRecTrackAlgorithms/src/RichTrackFunctionalCherenkovResolutions.h @@ -53,7 +53,7 @@ namespace Rich namespace Rec { - /** @class RichTrackFunctionalCherenkovResolutions RichRichTrackFunctionalCherenkovResolutions.h + /** @class FunctionalCherenkovResolutions RichRichTrackFunctionalCherenkovResolutions.h * * Computes the expected Cherenkov resolutions for the given track segments * -- GitLab From f5f46c8764569ff1a50bf04f7c86d322093f2970 Mon Sep 17 00:00:00 2001 From: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Fri, 24 Feb 2017 14:24:21 +0000 Subject: [PATCH 21/68] remove moved file --- .../src/application/PhotonReco/main.cpp | 81 ------------------- 1 file changed, 81 deletions(-) delete mode 100644 Rich/RichRecPhotonTools/src/application/PhotonReco/main.cpp diff --git a/Rich/RichRecPhotonTools/src/application/PhotonReco/main.cpp b/Rich/RichRecPhotonTools/src/application/PhotonReco/main.cpp deleted file mode 100644 index 20a2eb747d..0000000000 --- a/Rich/RichRecPhotonTools/src/application/PhotonReco/main.cpp +++ /dev/null @@ -1,81 +0,0 @@ - -// Quartic Solver -#include "RichRecUtils/QuarticSolver.h" - -// STL -#include <random> -#include <vector> -#include <iostream> -#include <string> -#include <typeinfo> - -// Make an instance of the quartic solver -Rich::Rec::QuarticSolver qSolver; - -Gaudi::XYZPoint sphReflPoint; - -class Data -{ -public: - typedef std::vector<Data> Vector; -public: - Gaudi::XYZPoint emissPnt; - Gaudi::XYZPoint centOfCurv; - Gaudi::XYZPoint virtDetPoint; - double radius; -public: - Data() - { - // randomn generator - static std::default_random_engine gen; - // Distributions for each member - static std::uniform_real_distribution<double> r_emiss_x(-800,800), r_emiss_y(-600,600), r_emiss_z(10000,10500); - static std::uniform_real_distribution<double> r_coc_x(-3000,3000), r_coc_y(-20,20), r_coc_z(3300,3400); - static std::uniform_real_distribution<double> r_vdp_x(-3000,3000), r_vdp_y(-200,200), r_vdp_z(8100,8200); - static std::uniform_real_distribution<float> r_rad(8500,8600); - // setup data - emissPnt = Gaudi::XYZPoint( r_emiss_x(gen), r_emiss_y(gen), r_emiss_z(gen) ); - centOfCurv = Gaudi::XYZPoint( r_coc_x(gen), r_coc_y(gen), r_coc_z(gen) ); - virtDetPoint = Gaudi::XYZPoint( r_vdp_x(gen), r_vdp_y(gen), r_vdp_z(gen) ); - radius = r_rad(gen); - } -}; - -template< class TYPE > -void solve( const Data& data ) -{ - qSolver.solve<TYPE>( data.emissPnt, - data.centOfCurv, - data.virtDetPoint, - data.radius, - sphReflPoint ); -} - -template< class TYPE > -void solve( const Data::Vector & dataV ) -{ - std::cout << "Solving Quartic Equation for " - << typeid(TYPE).name() - << " Photons ..." << std::endl; - // iterate over the data and solve it... - for ( const auto& data : dataV ) { solve<TYPE>(data); } -} - -int main ( int /*argc*/, char** /*argv*/ ) -{ - const unsigned int nPhotons = 1e6; - - Data::Vector dataV; - dataV.reserve( nPhotons ); - // Construct the data to work on - std::cout << "Creating " << nPhotons << " random photons ..." << std::endl; - for ( unsigned int i = 0; i < nPhotons; ++i ) { dataV.push_back( Data() ); } - - // run the solver for floats - solve<float>( dataV ); - - // run the solver for doubles - solve<double>( dataV ); - - return 0; -} -- GitLab From 83bba98f23cb07e920ee6ce840116196b219ed0c Mon Sep 17 00:00:00 2001 From: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Fri, 24 Feb 2017 14:24:41 +0000 Subject: [PATCH 22/68] Add Rich/RichRecTests to package list --- RecSys/CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/RecSys/CMakeLists.txt b/RecSys/CMakeLists.txt index 939db4b274..fce2385570 100644 --- a/RecSys/CMakeLists.txt +++ b/RecSys/CMakeLists.txt @@ -60,6 +60,7 @@ gaudi_depends_on_subdirs(Calo/CaloMoniDst Rich/RichFutureRecSys Rich/RichFutureRecMonitors Rich/RichFutureRecCheckers + Rich/RichRecTests Tf/FastPV Tf/FastVelo Tf/PatAlgorithms -- GitLab From 980ae285ac340bfc627eea252788fd1f56548c30 Mon Sep 17 00:00:00 2001 From: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Fri, 24 Feb 2017 14:25:09 +0000 Subject: [PATCH 23/68] Update alignment scripts --- .../RefractAndHPDJobs/CommonOptions.py | 2 +- .../scripts/RefractAndHPDJobs/GetLFNsByRun.py | 158 +++++++++++------- 2 files changed, 96 insertions(+), 64 deletions(-) diff --git a/Rich/RichAlignment/scripts/RefractAndHPDJobs/CommonOptions.py b/Rich/RichAlignment/scripts/RefractAndHPDJobs/CommonOptions.py index a051222bc3..af38d34c09 100644 --- a/Rich/RichAlignment/scripts/RefractAndHPDJobs/CommonOptions.py +++ b/Rich/RichAlignment/scripts/RefractAndHPDJobs/CommonOptions.py @@ -31,7 +31,7 @@ importOptions("$L0TCK/L0DUConfig.opts") # For 2016 data importOptions("$APPCONFIGOPTS/Brunel/DataType-2016.py") LHCbApp().DDDBtag = "dddb-20150724" -LHCbApp().CondDBtag = "cond-20160517" +LHCbApp().CondDBtag = "cond-20170120-1" # Aerogel Sub Tiles #CondDB().LocalTags["LHCBCOND"] = ["rich1-20110624"] diff --git a/Rich/RichAlignment/scripts/RefractAndHPDJobs/GetLFNsByRun.py b/Rich/RichAlignment/scripts/RefractAndHPDJobs/GetLFNsByRun.py index 516bc597b7..ef223eb1d1 100755 --- a/Rich/RichAlignment/scripts/RefractAndHPDJobs/GetLFNsByRun.py +++ b/Rich/RichAlignment/scripts/RefractAndHPDJobs/GetLFNsByRun.py @@ -42,6 +42,8 @@ elif 2013 == year : ConfigV = ['Collision13','Protonion13','Ionproton13','Ionsmog'] elif 2015 == year : ConfigV = ['Collision15','Collision15em','Protonhelium15','Protonneon15','Protonargon15','Lead15'] +elif 2016 == year : + ConfigV = ['Collision16'] else: print 'Unknown year', year DIRAC.exit(2) @@ -51,6 +53,10 @@ allOK = True # Dictionary for LFNs by Run RunLFNs = { } +polarity = "MagUp" +#polarity = "MagDown" +#polarity = "All" + startDate = getDate(year,startmonth,startday) endDate = getDate(year,lastmonth,lastday) dict = { 'StartDate' : startDate, @@ -81,80 +87,106 @@ else: for run in runs : if maxrun == -1 or run <= maxrun : - + nRun += 1 - for config in ConfigV : - - type = 91000000 # EXPRESS Stream - if year == 2009 : type = 90000000 # Use full stream for 2009 - if run > 71473 and run < 72332 : # Use FULL for first 14nb-1 in 2010 - type = 90000000 # FULL Stream - if run > 77595 and run < 77624 : # Express disappeared for unknown reasons - type = 90000000 # FULL Stream - if run > 100256 and run < 102177 : # Express turned off by accident after 09/2011 TS - type = 90000000 # FULL Stream - if config == 'Collision11_25' : # No express for 2011 25ns tests - type = 90000000 # FULL Stream - if config == 'Protonion12' : # (Currently) no express stream for pA data - type = 90000000 # FULL Stream - if config == 'Protonion13' or config == 'Ionproton13' : - type = 90000000 # FULL Stream - #if run > 77595 and run < 77624 : # Express disappeared for unknown reasons - if run > 157596 : # Express stream turned off in Run II - type = 90000000 # FULL Stream - - typeS = "EXPRESS" - if type == 90000000 : typeS = "FULL" - - # Processing pass. For 2011 express stream data used a Merged location - procpass = 'Real Data' - if year == 2011 and type != 90000000 : - procpass = 'Real Data/Merging' - - # Raw files - bkDict = { 'ConfigName' : 'LHCb', - 'ConfigVersion' : config, - 'ProcessingPass' : procpass, - 'FileType' : 'ALL', - 'StartRun' : run, - 'EndRun' : run, - 'EventType' : type } - resultB = database.getFilesWithGivenDataSets(bkDict) - - if not resultB['OK']: - print "Error querying BK with", bkDict, resultB['Message'] - allOK = False - else: - tmpLFNList = [ ] - for lfn in resultB['Value']: - filetype = lfn.split('.')[1] - if filetype == 'dst' or filetype == 'raw': - tmpLFNList += ["LFN:"+lfn.encode("ascii")] - tmpLFNList.sort() - if len(tmpLFNList) > 0 : - if run not in RunLFNs.keys() : RunLFNs[run] = [ ] - RunLFNs[run] += tmpLFNList - - if not allOK : break + # Polarity ? + res = database.getRunInformations(int(run)) + if polarity == "All" or polarity in res['Value']['DataTakingDescription'] : + + for config in ConfigV : + + type = 91000000 # EXPRESS Stream + if year == 2009 : type = 90000000 # Use full stream for 2009 + if run > 71473 and run < 72332 : # Use FULL for first 14nb-1 in 2010 + type = 90000000 # FULL Stream + if run > 77595 and run < 77624 : # Express disappeared for unknown reasons + type = 90000000 # FULL Stream + if run > 100256 and run < 102177 : # Express turned off by accident after 09/2011 TS + type = 90000000 # FULL Stream + if config == 'Collision11_25' : # No express for 2011 25ns tests + type = 90000000 # FULL Stream + if config == 'Protonion12' : # (Currently) no express stream for pA data + type = 90000000 # FULL Stream + if config == 'Protonion13' or config == 'Ionproton13' : + type = 90000000 # FULL Stream + #if run > 77595 and run < 77624 : # Express disappeared for unknown reasons + if run > 157596 : # Express stream turned off in Run II + type = 90000000 # FULL Stream + if config == 'Collision16' : + type = 90000000 # FULL Stream + + typeS = "EXPRESS" + if type == 90000000 : typeS = "FULL" + + # Processing pass. For 2011 express stream data used a Merged location + procpass = 'Real Data' + if year == 2011 and type != 90000000 : + procpass = 'Real Data/Merging' + + # Raw files + bkDict = { 'ConfigName' : 'LHCb', + 'ConfigVersion' : config, + 'ProcessingPass' : procpass, + 'FileType' : 'ALL', + 'StartRun' : run, + 'EndRun' : run, + 'EventType' : type } + resultB = database.getFilesWithGivenDataSets(bkDict) + + if not resultB['OK']: + + print "Error querying BK with", bkDict, resultB['Message'] + allOK = False + + else: + + tmpLFNList = [ ] - nLFNs = 0 - if run in RunLFNs.keys() : nLFNs = len(RunLFNs[run]) - if nLFNs > 0 : - print "(", nRun, "of", len(runs), ") Selected", nLFNs, "LFNs for run", run, ConfigV - print RunLFNs[run] - else: - print "(", nRun, "of", len(runs), ") No data selected for run", run, ConfigV + lfns = resultB['Value'] + tmplfns = list( set(lfns) ) + if len(tmplfns) != len(lfns) : + print "WARNING : run", run, "has duplicate LFNs" + print bkDict + print resultB['Value'] + lfns = tmplfns + + for lfn in lfns: + filetype = lfn.split('.')[1] + if filetype == 'dst' or filetype == 'raw': + tmpLFNList += ["LFN:"+lfn.encode("ascii")] + + tmpLFNList.sort() + if len(tmpLFNList) > 0 : + if run not in RunLFNs.keys() : RunLFNs[run] = [ ] + RunLFNs[run] += tmpLFNList + + if not allOK : break + + nLFNs = 0 + if run in RunLFNs.keys() : nLFNs = len(RunLFNs[run]) + if nLFNs > 0 : + print "(", nRun, "of", len(runs), ") Selected", nLFNs, "LFNs for run", run, ConfigV + #print RunLFNs[run] + else: + print "(", nRun, "of", len(runs), ") No data selected for run", run, ConfigV - else: + else : + + print "(", nRun, "of", len(runs), ") Run", run, "has wrong polarity" + else: + print "Skipping run", run if allOK : # Pickle the data if len(RunLFNs.keys()) > 0: - filename = "RunData/RunLFNs_"+startDate+"_"+endDate+".pck.bz2" + if polarity == "All" : + filename = "RunData/RunLFNs_"+startDate+"_"+endDate+".pck.bz2" + else : + filename = "RunData/RunLFNs_"+polarity+"_"+startDate+"_"+endDate+".pck.bz2" file = bz2.BZ2File(filename,"w") pickle.dump(RunLFNs,file) file.close() -- GitLab From 594cfb11a38fbd5bab65fd0182ba3297bb46d28d Mon Sep 17 00:00:00 2001 From: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Fri, 24 Feb 2017 19:07:26 +0000 Subject: [PATCH 24/68] update test application --- Rich/RichRecTests/src/RayTracing/main.cpp | 31 +++++++++++++++-------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/Rich/RichRecTests/src/RayTracing/main.cpp b/Rich/RichRecTests/src/RayTracing/main.cpp index 7b109c29e2..8340ef59ab 100644 --- a/Rich/RichRecTests/src/RayTracing/main.cpp +++ b/Rich/RichRecTests/src/RayTracing/main.cpp @@ -10,6 +10,10 @@ #include "LHCbMath/EigenTypes.h" #include "LHCbMath/VectorClassTypes.h" +// LHCb TemplatedGenVector +#include "TemplatedGenVector/DisplacementVector3D.h" +#include "TemplatedGenVector/PositionVector3D.h" + // Rich Utils #include "RichUtils/RichRayTracingUtils.h" #include "RichUtils/ZipRange.h" @@ -37,7 +41,7 @@ static std::uniform_real_distribution<double> c_x(3100,3200), c_y(10,15), c_z static std::uniform_real_distribution<double> r_rad(8500,8600); static std::uniform_real_distribution<double> p0(-0.002,0.002), p1(-0.2,0.2), p2(0.97,0.99), p3(-1300,1300); -template < typename POINT, typename VECTOR, typename PLANE, typename FTYPE > +template < typename POINT, typename VECTOR, typename FTYPE > class Data { public: @@ -46,7 +50,7 @@ public: POINT position; VECTOR direction; POINT CoC; - PLANE plane; + //PLANE plane; FTYPE radius{0}; public: template< typename INDATA > @@ -54,13 +58,13 @@ public: : position(ind.position), direction(ind.direction), CoC(ind.CoC), - plane(ind.plane), + // plane(ind.plane), radius(ind.radius) { } Data( ) : position ( p_x(gen), p_y(gen), p_z(gen) ), direction ( d_x(gen), d_y(gen), d_z(gen) ), CoC ( c_x(gen), c_y(gen), c_z(gen) ), - plane ( p0(gen), p1(gen), p2(gen), p3(gen) ), + //plane ( p0(gen), p1(gen), p2(gen), p3(gen) ), radius ( r_rad(gen) ) { } }; @@ -102,17 +106,24 @@ int main ( int /*argc*/, char** /*argv*/ ) const unsigned int nPhotons = 96 * 1e2; std::cout << "Creating " << nPhotons << " random photons ..." << std::endl; + // Templated GenVector + using LHCbXYZPointD = LHCbROOT::Math::PositionVector3D<LHCbROOT::Math::Cartesian3D<double>,LHCbROOT::Math::DefaultCoordinateSystemTag>; + using LHCbXYZVectorD = LHCbROOT::Math::DisplacementVector3D<LHCbROOT::Math::Cartesian3D<double>,LHCbROOT::Math::DefaultCoordinateSystemTag>; + using LHCbXYZPointF = LHCbROOT::Math::PositionVector3D<LHCbROOT::Math::Cartesian3D<float>,LHCbROOT::Math::DefaultCoordinateSystemTag>; + using LHCbXYZVectorF = LHCbROOT::Math::DisplacementVector3D<LHCbROOT::Math::Cartesian3D<float>,LHCbROOT::Math::DefaultCoordinateSystemTag>; + //using LHCbPlan + // Vc - using VcXYZPointD = ROOT::Math::PositionVector3D<ROOT::Math::Cartesian3D<Vc::double_v>,ROOT::Math::DefaultCoordinateSystemTag>; - using VcXYZVectorD = ROOT::Math::DisplacementVector3D<ROOT::Math::Cartesian3D<Vc::double_v>,ROOT::Math::DefaultCoordinateSystemTag>; - using VcXYZPointF = ROOT::Math::PositionVector3D<ROOT::Math::Cartesian3D<Vc::float_v>,ROOT::Math::DefaultCoordinateSystemTag>; - using VcXYZVectorF = ROOT::Math::DisplacementVector3D<ROOT::Math::Cartesian3D<Vc::float_v>,ROOT::Math::DefaultCoordinateSystemTag>; + using VcXYZPointD = LHCbROOT::Math::PositionVector3D<ROOT::Math::Cartesian3D<Vc::double_v>,ROOT::Math::DefaultCoordinateSystemTag>; + using VcXYZVectorD = LHCbROOT::Math::DisplacementVector3D<ROOT::Math::Cartesian3D<Vc::double_v>,ROOT::Math::DefaultCoordinateSystemTag>; + using VcXYZPointF = LHCbROOT::Math::PositionVector3D<ROOT::Math::Cartesian3D<Vc::float_v>,ROOT::Math::DefaultCoordinateSystemTag>; + using VcXYZVectorF = LHCbROOT::Math::DisplacementVector3D<ROOT::Math::Cartesian3D<Vc::float_v>,ROOT::Math::DefaultCoordinateSystemTag>; //if ( false ) { // Data in 'ROOT' SMatrix double format - Data<Gaudi::XYZPoint,Gaudi::XYZVector,Gaudi::Plane3D,Gaudi::XYZVector::Scalar>::Vector root_dataV( nPhotons ); + Data<LHCbXYZPointD,LHCbXYZVectorD,Gaudi::XYZVector::Scalar>::Vector root_dataV( nPhotons ); auto resROOT = rayTrace( root_dataV ); std::cout << "ROOT double " << resROOT << std::endl; @@ -145,7 +156,7 @@ int main ( int /*argc*/, char** /*argv*/ ) { // Data in 'ROOT' SMatrix double format - Data<Gaudi::XYZPointF,Gaudi::XYZVectorF,Gaudi::Plane3DF,Gaudi::XYZVectorF::Scalar>::Vector root_dataV( nPhotons ); + Data<Gaudi::XYZPointF,Gaudi::XYZVectorF,Gaudi::XYZVectorF::Scalar>::Vector root_dataV( nPhotons ); auto resROOT = rayTrace( root_dataV ); std::cout << "ROOT float " << resROOT << std::endl; -- GitLab From 9240da05695973d5b18e78dd00760b2db82f2dfa Mon Sep 17 00:00:00 2001 From: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Sat, 25 Feb 2017 13:40:47 +0000 Subject: [PATCH 25/68] Extend test applications to be built with multiple instruction sets --- Rich/RichRecTests/CMakeLists.txt | 59 ++++++++++++++--- .../src/PhotonReco/{main.cpp => main.icpp} | 0 Rich/RichRecTests/src/PhotonReco/main_avx.cpp | 2 + .../RichRecTests/src/PhotonReco/main_avx2.cpp | 2 + .../src/PhotonReco/main_avx2fma.cpp | 2 + .../RichRecTests/src/PhotonReco/main_sse4.cpp | 2 + .../src/RayTracing/{main.cpp => main.icpp} | 64 ++++++++++--------- Rich/RichRecTests/src/RayTracing/main_avx.cpp | 2 + .../RichRecTests/src/RayTracing/main_avx2.cpp | 2 + .../src/RayTracing/main_avx2fma.cpp | 2 + .../RichRecTests/src/RayTracing/main_sse4.cpp | 2 + 11 files changed, 101 insertions(+), 38 deletions(-) rename Rich/RichRecTests/src/PhotonReco/{main.cpp => main.icpp} (100%) create mode 100644 Rich/RichRecTests/src/PhotonReco/main_avx.cpp create mode 100644 Rich/RichRecTests/src/PhotonReco/main_avx2.cpp create mode 100644 Rich/RichRecTests/src/PhotonReco/main_avx2fma.cpp create mode 100644 Rich/RichRecTests/src/PhotonReco/main_sse4.cpp rename Rich/RichRecTests/src/RayTracing/{main.cpp => main.icpp} (73%) create mode 100644 Rich/RichRecTests/src/RayTracing/main_avx.cpp create mode 100644 Rich/RichRecTests/src/RayTracing/main_avx2.cpp create mode 100644 Rich/RichRecTests/src/RayTracing/main_avx2fma.cpp create mode 100644 Rich/RichRecTests/src/RayTracing/main_sse4.cpp diff --git a/Rich/RichRecTests/CMakeLists.txt b/Rich/RichRecTests/CMakeLists.txt index 2c8215cc26..88264c4108 100644 --- a/Rich/RichRecTests/CMakeLists.txt +++ b/Rich/RichRecTests/CMakeLists.txt @@ -28,19 +28,62 @@ include_directories(SYSTEM ${Boost_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS} if(GAUDI_BUILD_TESTS) - gaudi_add_executable(RichPhotonRecoTest - src/PhotonReco/*.cpp + gaudi_add_executable(RichPhotonRecoTestSSE4 + src/PhotonReco/main_sse4.cpp INCLUDE_DIRS ROOT Vc Eigen GSL VectorClass src LINK_LIBRARIES LHCbMathLib GSL GaudiKernel) - target_link_libraries( RichPhotonRecoTest -lrt ) + target_link_libraries( RichPhotonRecoTestSSE4 -lrt ) + set_property(SOURCE src/RayTracing/main_sse4.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -msse4.2 " ) - set_property(SOURCE src/RayTracing/main.cpp PROPERTY COMPILE_FLAGS " -Wno-ignored-attributes" ) - #set_property(SOURCE src/RayTracing/main.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -mfma -mavx2 -O3 -fabi-version=0 -fabi-compat-version=0 -ffp-contract=fast " ) + gaudi_add_executable(RichPhotonRecoTestAVX + src/PhotonReco/main_avx.cpp + INCLUDE_DIRS ROOT Vc Eigen GSL VectorClass src + LINK_LIBRARIES LHCbMathLib GSL GaudiKernel) + target_link_libraries( RichPhotonRecoTestAVX -lrt ) + set_property(SOURCE src/RayTracing/main_avx.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -mavx -fabi-version=0 -fabi-compat-version=0 -ffp-contract=fast " ) + + gaudi_add_executable(RichPhotonRecoTestAVX2 + src/PhotonReco/main_avx2.cpp + INCLUDE_DIRS ROOT Vc Eigen GSL VectorClass src + LINK_LIBRARIES LHCbMathLib GSL GaudiKernel) + target_link_libraries( RichPhotonRecoTestAVX2 -lrt ) + set_property(SOURCE src/RayTracing/main_avx2.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -mavx2 -fabi-version=0 -fabi-compat-version=0 -ffp-contract=fast " ) + + gaudi_add_executable(RichPhotonRecoTestAVX2FMA + src/PhotonReco/main_avx2fma.cpp + INCLUDE_DIRS ROOT Vc Eigen GSL VectorClass src + LINK_LIBRARIES LHCbMathLib GSL GaudiKernel) + target_link_libraries( RichPhotonRecoTestAVX2FMA -lrt ) + set_property(SOURCE src/RayTracing/main_avx2fma.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -mfma -mavx2 -fabi-version=0 -fabi-compat-version=0 -ffp-contract=fast " ) + + + + gaudi_add_executable(RichRayTracingTestSSE4 + src/RayTracing/main_sse4.cpp + INCLUDE_DIRS ROOT Vc Eigen GSL VectorClass src + LINK_LIBRARIES LHCbMathLib GSL GaudiKernel) + target_link_libraries( RichRayTracingTestSSE4 "-lrt ${Vc_LIB_DIR}/libVc.a" ) + set_property(SOURCE src/RayTracing/main_sse4.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-ignored-attributes -msse4.2 " ) + + gaudi_add_executable(RichRayTracingTestAVX + src/RayTracing/main_avx.cpp + INCLUDE_DIRS ROOT Vc Eigen GSL VectorClass src + LINK_LIBRARIES LHCbMathLib GSL GaudiKernel) + target_link_libraries( RichRayTracingTestAVX "-lrt ${Vc_LIB_DIR}/libVc.a" ) + set_property(SOURCE src/RayTracing/main_avx.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-ignored-attributes -mavx -fabi-version=0 -fabi-compat-version=0 -ffp-contract=fast " ) + + gaudi_add_executable(RichRayTracingTestAVX2 + src/RayTracing/main_avx2.cpp + INCLUDE_DIRS ROOT Vc Eigen GSL VectorClass src + LINK_LIBRARIES LHCbMathLib GSL GaudiKernel) + target_link_libraries( RichRayTracingTestAVX2 "-lrt ${Vc_LIB_DIR}/libVc.a" ) + set_property(SOURCE src/RayTracing/main_avx2.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-ignored-attributes -mavx2 -fabi-version=0 -fabi-compat-version=0 -ffp-contract=fast " ) - gaudi_add_executable(RichRayTracingTest - src/RayTracing/*.cpp + gaudi_add_executable(RichRayTracingTestAVX2FMA + src/RayTracing/main_avx2fma.cpp INCLUDE_DIRS ROOT Vc Eigen GSL VectorClass src LINK_LIBRARIES LHCbMathLib GSL GaudiKernel) - target_link_libraries( RichRayTracingTest "-lrt ${Vc_LIB_DIR}/libVc.a" ) + target_link_libraries( RichRayTracingTestAVX2FMA "-lrt ${Vc_LIB_DIR}/libVc.a" ) + set_property(SOURCE src/RayTracing/main_avx2fma.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-ignored-attributes -mfma -mavx2 -fabi-version=0 -fabi-compat-version=0 -ffp-contract=fast " ) endif() diff --git a/Rich/RichRecTests/src/PhotonReco/main.cpp b/Rich/RichRecTests/src/PhotonReco/main.icpp similarity index 100% rename from Rich/RichRecTests/src/PhotonReco/main.cpp rename to Rich/RichRecTests/src/PhotonReco/main.icpp diff --git a/Rich/RichRecTests/src/PhotonReco/main_avx.cpp b/Rich/RichRecTests/src/PhotonReco/main_avx.cpp new file mode 100644 index 0000000000..c673656633 --- /dev/null +++ b/Rich/RichRecTests/src/PhotonReco/main_avx.cpp @@ -0,0 +1,2 @@ + +#include "main.icpp" diff --git a/Rich/RichRecTests/src/PhotonReco/main_avx2.cpp b/Rich/RichRecTests/src/PhotonReco/main_avx2.cpp new file mode 100644 index 0000000000..c673656633 --- /dev/null +++ b/Rich/RichRecTests/src/PhotonReco/main_avx2.cpp @@ -0,0 +1,2 @@ + +#include "main.icpp" diff --git a/Rich/RichRecTests/src/PhotonReco/main_avx2fma.cpp b/Rich/RichRecTests/src/PhotonReco/main_avx2fma.cpp new file mode 100644 index 0000000000..c673656633 --- /dev/null +++ b/Rich/RichRecTests/src/PhotonReco/main_avx2fma.cpp @@ -0,0 +1,2 @@ + +#include "main.icpp" diff --git a/Rich/RichRecTests/src/PhotonReco/main_sse4.cpp b/Rich/RichRecTests/src/PhotonReco/main_sse4.cpp new file mode 100644 index 0000000000..c673656633 --- /dev/null +++ b/Rich/RichRecTests/src/PhotonReco/main_sse4.cpp @@ -0,0 +1,2 @@ + +#include "main.icpp" diff --git a/Rich/RichRecTests/src/RayTracing/main.cpp b/Rich/RichRecTests/src/RayTracing/main.icpp similarity index 73% rename from Rich/RichRecTests/src/RayTracing/main.cpp rename to Rich/RichRecTests/src/RayTracing/main.icpp index 8340ef59ab..8f446edfb7 100644 --- a/Rich/RichRecTests/src/RayTracing/main.cpp +++ b/Rich/RichRecTests/src/RayTracing/main.icpp @@ -8,11 +8,12 @@ // LHCbMath #include "LHCbMath/EigenTypes.h" -#include "LHCbMath/VectorClassTypes.h" +//#include "LHCbMath/VectorClassTypes.h" // LHCb TemplatedGenVector #include "TemplatedGenVector/DisplacementVector3D.h" #include "TemplatedGenVector/PositionVector3D.h" +#include "TemplatedGenVector/Plane3D.h" // Rich Utils #include "RichUtils/RichRayTracingUtils.h" @@ -41,16 +42,16 @@ static std::uniform_real_distribution<double> c_x(3100,3200), c_y(10,15), c_z static std::uniform_real_distribution<double> r_rad(8500,8600); static std::uniform_real_distribution<double> p0(-0.002,0.002), p1(-0.2,0.2), p2(0.97,0.99), p3(-1300,1300); -template < typename POINT, typename VECTOR, typename FTYPE > +template < typename POINT, typename VECTOR, typename PLANE, typename FTYPE > class Data { public: - typedef std::vector<Data> Vector; + typedef std::vector< Data, Vc::Allocator<Data> > Vector; public: POINT position; VECTOR direction; POINT CoC; - //PLANE plane; + PLANE plane; FTYPE radius{0}; public: template< typename INDATA > @@ -58,13 +59,13 @@ public: : position(ind.position), direction(ind.direction), CoC(ind.CoC), - // plane(ind.plane), + plane(ind.plane), radius(ind.radius) { } Data( ) : position ( p_x(gen), p_y(gen), p_z(gen) ), direction ( d_x(gen), d_y(gen), d_z(gen) ), CoC ( c_x(gen), c_y(gen), c_z(gen) ), - //plane ( p0(gen), p1(gen), p2(gen), p3(gen) ), + plane ( p0(gen), p1(gen), p2(gen), p3(gen) ), radius ( r_rad(gen) ) { } }; @@ -75,6 +76,7 @@ inline void trace( DATA & dataV ) for ( auto & data : dataV ) { reflectSpherical( data.position, data.direction, data.CoC, data.radius ); + reflectPlane ( data.position, data.direction, data.plane ); } } @@ -104,6 +106,7 @@ int main ( int /*argc*/, char** /*argv*/ ) { const unsigned int nPhotons = 96 * 1e2; + //const unsigned int nPhotons = 8; std::cout << "Creating " << nPhotons << " random photons ..." << std::endl; // Templated GenVector @@ -111,43 +114,44 @@ int main ( int /*argc*/, char** /*argv*/ ) using LHCbXYZVectorD = LHCbROOT::Math::DisplacementVector3D<LHCbROOT::Math::Cartesian3D<double>,LHCbROOT::Math::DefaultCoordinateSystemTag>; using LHCbXYZPointF = LHCbROOT::Math::PositionVector3D<LHCbROOT::Math::Cartesian3D<float>,LHCbROOT::Math::DefaultCoordinateSystemTag>; using LHCbXYZVectorF = LHCbROOT::Math::DisplacementVector3D<LHCbROOT::Math::Cartesian3D<float>,LHCbROOT::Math::DefaultCoordinateSystemTag>; - //using LHCbPlan + using LHCbPlane3DD = LHCbROOT::Math::Plane3D<double>; + using LHCbPlane3DF = LHCbROOT::Math::Plane3D<float>; // Vc - using VcXYZPointD = LHCbROOT::Math::PositionVector3D<ROOT::Math::Cartesian3D<Vc::double_v>,ROOT::Math::DefaultCoordinateSystemTag>; - using VcXYZVectorD = LHCbROOT::Math::DisplacementVector3D<ROOT::Math::Cartesian3D<Vc::double_v>,ROOT::Math::DefaultCoordinateSystemTag>; - using VcXYZPointF = LHCbROOT::Math::PositionVector3D<ROOT::Math::Cartesian3D<Vc::float_v>,ROOT::Math::DefaultCoordinateSystemTag>; - using VcXYZVectorF = LHCbROOT::Math::DisplacementVector3D<ROOT::Math::Cartesian3D<Vc::float_v>,ROOT::Math::DefaultCoordinateSystemTag>; + using VcXYZPointD = LHCbROOT::Math::PositionVector3D<LHCbROOT::Math::Cartesian3D<Vc::double_v>,LHCbROOT::Math::DefaultCoordinateSystemTag>; + using VcXYZVectorD = LHCbROOT::Math::DisplacementVector3D<LHCbROOT::Math::Cartesian3D<Vc::double_v>,LHCbROOT::Math::DefaultCoordinateSystemTag>; + using VcXYZPointF = LHCbROOT::Math::PositionVector3D<LHCbROOT::Math::Cartesian3D<Vc::float_v>,LHCbROOT::Math::DefaultCoordinateSystemTag>; + using VcXYZVectorF = LHCbROOT::Math::DisplacementVector3D<LHCbROOT::Math::Cartesian3D<Vc::float_v>,LHCbROOT::Math::DefaultCoordinateSystemTag>; + using VcPlane3DD = LHCbROOT::Math::Plane3D<Vc::double_v>; + using VcPlane3DF = LHCbROOT::Math::Plane3D<Vc::float_v>; //if ( false ) { // Data in 'ROOT' SMatrix double format - Data<LHCbXYZPointD,LHCbXYZVectorD,Gaudi::XYZVector::Scalar>::Vector root_dataV( nPhotons ); + Data<LHCbXYZPointD,LHCbXYZVectorD,LHCbPlane3DD,LHCbXYZPointD::Scalar>::Vector root_dataV( nPhotons ); auto resROOT = rayTrace( root_dataV ); std::cout << "ROOT double " << resROOT << std::endl; // Same data in Eigen double format - Data<LHCb::Math::Eigen::XYZPoint<double>,LHCb::Math::Eigen::XYZVector<double>,double>::Vector eigen_dataV( nPhotons ); + Data<LHCb::Math::Eigen::XYZPoint<double>,LHCb::Math::Eigen::XYZVector<double>,LHCb::Math::Eigen::Plane3D<double>,double>::Vector eigen_dataV( nPhotons ); auto resEIGEN = rayTrace( eigen_dataV ); std::cout << "Eigen double " << resEIGEN << " speedup " << (float)resROOT/(float)resEIGEN << std::endl; - - // _mm256_zeroupper(); // Same data in VectorClass double format - Data<LHCb::Math::VectorClass::XYZPoint<double>,LHCb::Math::VectorClass::XYZVector<double>,double>::Vector vclass_dataV( nPhotons ); - auto resVClass = rayTrace( vclass_dataV ); - std::cout << "VectorClass double " << resVClass << " speedup " << (float)resROOT/(float)resVClass << std::endl; + //Data<LHCb::Math::VectorClass::XYZPoint<double>,LHCb::Math::VectorClass::XYZVector<double>,double>::Vector vclass_dataV( nPhotons ); + //auto resVClass = rayTrace( vclass_dataV ); + //std::cout << "VectorClass double " << resVClass << " speedup " << (float)resROOT/(float)resVClass << std::endl; // Vc float - Data<VcXYZPointD,VcXYZVectorD,Vc::double_v>::Vector VC_dataV( nPhotons / Vc::double_v::Size ); + Data<VcXYZPointD,VcXYZVectorD,VcPlane3DD,Vc::double_v>::Vector VC_dataV( nPhotons / Vc::double_v::Size ); auto resVC = rayTrace( VC_dataV ); std::cout << "Vc double " << resVC << " speedup " << (float)resROOT/(float)resVC << std::endl; // make sure we are not optimized away asm volatile ("" : "+x"(resROOT)); asm volatile ("" : "+x"(resEIGEN)); - asm volatile ("" : "+x"(resVClass)); + //asm volatile ("" : "+x"(resVClass)); asm volatile ("" : "+x"(resVC)); } @@ -155,30 +159,30 @@ int main ( int /*argc*/, char** /*argv*/ ) //if ( false ) { - // Data in 'ROOT' SMatrix double format - Data<Gaudi::XYZPointF,Gaudi::XYZVectorF,Gaudi::XYZVectorF::Scalar>::Vector root_dataV( nPhotons ); + // Data in 'ROOT' SMatrix float format + Data<LHCbXYZPointF,LHCbXYZVectorF,LHCbPlane3DF,LHCbXYZPointF::Scalar>::Vector root_dataV( nPhotons ); auto resROOT = rayTrace( root_dataV ); std::cout << "ROOT float " << resROOT << std::endl; - // Same data in Eigen double format - Data<LHCb::Math::Eigen::XYZPoint<float>,LHCb::Math::Eigen::XYZVector<float>,float>::Vector eigen_dataV( nPhotons ); + // Same data in Eigen float format + Data<LHCb::Math::Eigen::XYZPoint<float>,LHCb::Math::Eigen::XYZVector<float>,LHCb::Math::Eigen::Plane3D<float>,float>::Vector eigen_dataV( nPhotons ); auto resEIGEN = rayTrace( eigen_dataV ); std::cout << "Eigen float " << resEIGEN << " speedup " << (float)resROOT/(float)resEIGEN << std::endl; - // Same data in VectorClass double format - Data<LHCb::Math::VectorClass::XYZPoint<float>,LHCb::Math::VectorClass::XYZVector<float>,float>::Vector vclass_dataV( nPhotons ); - auto resVClass = rayTrace( vclass_dataV ); - std::cout << "VectorClass float " << resVClass << " speedup " << (float)resROOT/(float)resVClass << std::endl; + // Same data in VectorClass float format + //Data<LHCb::Math::VectorClass::XYZPoint<float>,LHCb::Math::VectorClass::XYZVector<float>,float>::Vector vclass_dataV( nPhotons ); + //auto resVClass = rayTrace( vclass_dataV ); + //std::cout << "VectorClass float " << resVClass << " speedup " << (float)resROOT/(float)resVClass << std::endl; // Vc float - Data<VcXYZPointF,VcXYZVectorF,Vc::float_v>::Vector VC_dataV( nPhotons / Vc::float_v::Size ); + Data<VcXYZPointF,VcXYZVectorF,VcPlane3DF,Vc::float_v>::Vector VC_dataV( nPhotons / Vc::float_v::Size ); auto resVC = rayTrace( VC_dataV ); std::cout << "Vc float " << resVC << " speedup " << (float)resROOT/(float)resVC << std::endl; // make sure we are not optimized away asm volatile ("" : "+x"(resROOT)); asm volatile ("" : "+x"(resEIGEN)); - asm volatile ("" : "+x"(resVClass)); + //asm volatile ("" : "+x"(resVClass)); asm volatile ("" : "+x"(resVC)); } diff --git a/Rich/RichRecTests/src/RayTracing/main_avx.cpp b/Rich/RichRecTests/src/RayTracing/main_avx.cpp new file mode 100644 index 0000000000..c673656633 --- /dev/null +++ b/Rich/RichRecTests/src/RayTracing/main_avx.cpp @@ -0,0 +1,2 @@ + +#include "main.icpp" diff --git a/Rich/RichRecTests/src/RayTracing/main_avx2.cpp b/Rich/RichRecTests/src/RayTracing/main_avx2.cpp new file mode 100644 index 0000000000..c673656633 --- /dev/null +++ b/Rich/RichRecTests/src/RayTracing/main_avx2.cpp @@ -0,0 +1,2 @@ + +#include "main.icpp" diff --git a/Rich/RichRecTests/src/RayTracing/main_avx2fma.cpp b/Rich/RichRecTests/src/RayTracing/main_avx2fma.cpp new file mode 100644 index 0000000000..c673656633 --- /dev/null +++ b/Rich/RichRecTests/src/RayTracing/main_avx2fma.cpp @@ -0,0 +1,2 @@ + +#include "main.icpp" diff --git a/Rich/RichRecTests/src/RayTracing/main_sse4.cpp b/Rich/RichRecTests/src/RayTracing/main_sse4.cpp new file mode 100644 index 0000000000..c673656633 --- /dev/null +++ b/Rich/RichRecTests/src/RayTracing/main_sse4.cpp @@ -0,0 +1,2 @@ + +#include "main.icpp" -- GitLab From 0e1e553fbb960372eb5833869d2b9c22cf72eebf Mon Sep 17 00:00:00 2001 From: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Wed, 1 Mar 2017 23:44:52 +0100 Subject: [PATCH 26/68] Add developmental version of a SIMD implementation of the Cherenkov cone ray tracing algorithm --- .../CMakeLists.txt | 2 +- .../RichFutureRecSys/ConfiguredRichReco.py | 15 +- .../CMakeLists.txt | 21 +- .../src/RichRayTraceCherenkovConesSIMD.cpp | 90 ++++++ .../src/RichRayTraceCherenkovConesSIMD.h | 201 ++++++++++++++ .../src/RichRayTraceCherenkovConesSIMD.icpp | 261 ++++++++++++++++++ .../src/avx/RichRayTraceCherenkovCones.cpp | 14 + .../src/avx2/RichRayTraceCherenkovCones.cpp | 14 + .../generic/RichRayTraceCherenkovCones.cpp | 14 + .../src/sse4/RichRayTraceCherenkovCones.cpp | 14 + Rich/RichRecTests/CMakeLists.txt | 35 +-- Rich/RichRecTests/src/RayTracing/main.icpp | 19 +- 12 files changed, 667 insertions(+), 33 deletions(-) create mode 100644 Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovConesSIMD.cpp create mode 100644 Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovConesSIMD.h create mode 100644 Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovConesSIMD.icpp create mode 100644 Rich/RichFutureRecTrackAlgorithms/src/avx/RichRayTraceCherenkovCones.cpp create mode 100644 Rich/RichFutureRecTrackAlgorithms/src/avx2/RichRayTraceCherenkovCones.cpp create mode 100644 Rich/RichFutureRecTrackAlgorithms/src/generic/RichRayTraceCherenkovCones.cpp create mode 100644 Rich/RichFutureRecTrackAlgorithms/src/sse4/RichRayTraceCherenkovCones.cpp diff --git a/Rich/RichFutureRecPhotonAlgorithms/CMakeLists.txt b/Rich/RichFutureRecPhotonAlgorithms/CMakeLists.txt index 5ccf26d32e..a3c59f6df2 100644 --- a/Rich/RichFutureRecPhotonAlgorithms/CMakeLists.txt +++ b/Rich/RichFutureRecPhotonAlgorithms/CMakeLists.txt @@ -17,7 +17,7 @@ include_directories(SYSTEM ${Boost_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS} ${EIGEN_INCLUDE_DIRS}) # For testing high vectorisation and optimisation levels -#set_property(SOURCE src/RichQuarticPhotonReco.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -msse4 -O3 " ) +#set_property(SOURCE src/RichQuarticPhotonReco.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -O3 -mavx2 -mfma -fabi-version=0 -fabi-compat-version=0 -ffp-contract=fast " ) gaudi_add_module(RichFutureRecPhotonAlgorithms src/*.cpp diff --git a/Rich/RichFutureRecSys/python/RichFutureRecSys/ConfiguredRichReco.py b/Rich/RichFutureRecSys/python/RichFutureRecSys/ConfiguredRichReco.py index e99f4138a7..9fc833512e 100644 --- a/Rich/RichFutureRecSys/python/RichFutureRecSys/ConfiguredRichReco.py +++ b/Rich/RichFutureRecSys/python/RichFutureRecSys/ConfiguredRichReco.py @@ -137,7 +137,7 @@ def RichRecoSequence( GroupName = "", # Optional name given to this group. preloadGeometry = False, # Number points for mass hypothesis ring ray tracing - NRingPoints = ( 100, 100, 100 ), + NRingPoints = ( 96, 96, 96 ), # Track Extrapolator type trackExtrapolator = "TrackRungeKuttaExtrapolator", @@ -322,6 +322,7 @@ def RichRecoSequence( GroupName = "", # Optional name given to this group. from Configurables import Rich__Future__Rec__TrackEmittedCherenkovAngles as EmittedCherenkovAngles from Configurables import Rich__Future__Rec__TrackSignalCherenkovAngles as SignalCherenkovAngles from Configurables import Rich__Future__Rec__RayTraceCherenkovCones as EmittedMassCones + from Configurables import Rich__Future__Rec__RayTraceCherenkovConesSIMD as EmittedMassConesSIMD from Configurables import Rich__Future__Rec__GeomEffCKMassRings as GeomEff from Configurables import Rich__Future__Rec__TrackFunctionalCherenkovResolutions as TrackCKResolutions from Configurables import Rich__Future__Rec__SelectTrackSegments as SelectTrackSegments @@ -386,6 +387,16 @@ def RichRecoSequence( GroupName = "", # Optional name given to this group. # Options emitMassCones.NRingPoints = NRingPoints + # Cherenkov mass cones using emitted spectra SIMD + emitMassConesSIMD = makeRichAlg( EmittedMassConesSIMD, "RichMassConesSIMD"+name, algprops ) + # Input + emitMassConesSIMD.TrackSegmentsLocation = locs["TrackSegmentsLocation"] + emitMassConesSIMD.CherenkovAnglesLocation = locs["EmittedCherenkovAnglesLocation"] + # Output + emitMassConesSIMD.MassHypothesisRingsLocation = locs["EmittedMassHypothesisRingsLocation"]+"SIMD" + # Options + emitMassConesSIMD.NRingPoints = NRingPoints + # Detectable photon yields detY = makeRichAlg( DetectableYields, "RichDetectableYields"+name, algprops ) # Inputs @@ -454,7 +465,7 @@ def RichRecoSequence( GroupName = "", # Optional name given to this group. segs = GaudiSequencer( "RichTracks" + name, MeasureTime = MeasureTime, Members = [ segCr, tkGloPnts, tkLocPnts, emitY, - emitChAngles, emitMassCones, detY, + emitChAngles, emitMassCones, emitMassConesSIMD, detY, geomEff, tkSel, sigYields, sigChAngles, tkRes ] ) # Add to final sequence tkSeq.Members += [ segs ] diff --git a/Rich/RichFutureRecTrackAlgorithms/CMakeLists.txt b/Rich/RichFutureRecTrackAlgorithms/CMakeLists.txt index d0eb77b7e8..9873e24314 100644 --- a/Rich/RichFutureRecTrackAlgorithms/CMakeLists.txt +++ b/Rich/RichFutureRecTrackAlgorithms/CMakeLists.txt @@ -8,17 +8,28 @@ gaudi_depends_on_subdirs(Rich/RichFutureRecBase Rich/RichUtils Rich/RichFutureUtils Tr/TrackKernel - Tr/TrackInterfaces) + Tr/TrackInterfaces + Kernel/TemplatedGenVector + Kernel/Vc + Kernel/VectorClass) find_package(ROOT) find_package(Boost) find_package(GSL) find_package(VDT) +find_package(Vc) -include_directories(SYSTEM ${Boost_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS}) +include_directories(SYSTEM ${Boost_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS} ${Vc_INCLUDE_DIR}) gaudi_add_module(RichFutureRecTrackAlgorithms - src/*.cpp - INCLUDE_DIRS Boost GSL VDT Rich/RichFutureRecBase Rich/RichUtils Rich/RichFutureUtils Tr/TrackInterfaces Tr/TrackKernel - LINK_LIBRARIES Boost GSL VDT RichFutureRecBase RichUtils RichFutureUtils) + src/*.cpp src/generic/*.cpp src/sse4/*.cpp src/avx/*.cpp src/avx2/*.cpp + INCLUDE_DIRS Vc Boost GSL VDT Kernel/VectorClass Rich/RichFutureRecBase Rich/RichUtils Rich/RichFutureUtils Tr/TrackInterfaces Tr/TrackKernel + LINK_LIBRARIES Boost GSL VDT RichFutureRecBase RichUtils RichFutureUtils TemplatedGenVectorLib ) +target_link_libraries( RichFutureRecTrackAlgorithms "${Vc_LIB_DIR}/libVc.a" ) + +set_property(SOURCE src/RichRayTraceCherenkovConesSIMD.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-ignored-attributes " ) +set_property(SOURCE src/generic/RichRayTraceCherenkovCones.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-ignored-attributes " ) +set_property(SOURCE src/sse4/RichRayTraceCherenkovCones.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-ignored-attributes -O3 -msse4.2 " ) +set_property(SOURCE src/avx/RichRayTraceCherenkovCones.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-ignored-attributes -O3 -mavx -fabi-version=0 -fabi-compat-version=0 -ffp-contract=fast " ) +set_property(SOURCE src/avx2/RichRayTraceCherenkovCones.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-ignored-attributes -O3 -mavx2 -mfma -fabi-version=0 -fabi-compat-version=0 -ffp-contract=fast " ) diff --git a/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovConesSIMD.cpp b/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovConesSIMD.cpp new file mode 100644 index 0000000000..f73429cae1 --- /dev/null +++ b/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovConesSIMD.cpp @@ -0,0 +1,90 @@ + +// local +#include "RichRayTraceCherenkovConesSIMD.h" + +// All code is in general Rich reconstruction namespace +using namespace Rich::Future::Rec; + +//============================================================================= + +RayTraceCherenkovConesSIMD::RayTraceCherenkovConesSIMD( const std::string& name, + ISvcLocator* pSvcLocator ) + : Transformer ( name, pSvcLocator, + { KeyValue{ "TrackSegmentsLocation", LHCb::RichTrackSegmentLocation::Default }, + KeyValue{ "CherenkovAnglesLocation", CherenkovAnglesLocation::Emitted } }, + { KeyValue{ "MassHypothesisRingsLocation", MassHypoRingsLocation::Emitted } } ) +{ + //declareProperty( "RayTracingTool", m_rayTrace ); + // debugging + //setProperty( "OutputLevel", MSG::VERBOSE ); +} + +//============================================================================= + +StatusCode RayTraceCherenkovConesSIMD::initialize() +{ + // Sets up various tools and services + auto sc = Transformer::initialize(); + if ( !sc ) return sc; + + // load tools + //sc = sc && m_rayTrace.retrieve(); + sc = sc && m_idTool.retrieve(); + sc = sc && m_mirrorSegFinder.retrieve(); + + // RICH detector elements + m_rich[Rich::Rich1] = getDet<DeRich>( DeRichLocations::Rich1 ); + m_rich[Rich::Rich2] = getDet<DeRich>( DeRichLocations::Rich2 ); + + // loop over radiators + for ( const auto rad : Rich::radiators() ) + { + // Check # photon is exactly divisible by 8 (for SIMD vectors without padding) + if ( m_nPoints[rad] % 8 != 0 ) + { + return Error( "# photons must be a multiple of 8 to avoid need for SIMD padding" ); + } + // Fill cos and sin values + m_cosSinPhiV[rad].clear(); + m_cosSinPhiV[rad].reserve( m_nPoints[rad] ); + const auto incPhi = Gaudi::Units::twopi / static_cast<double>(m_nPoints[rad]); + double ckPhi = 0.0; + for ( unsigned int iPhot = 0; iPhot < m_nPoints[rad]; ++iPhot, ckPhi+=incPhi ) + { m_cosSinPhiV[rad].emplace_back( ckPhi ); } + // bailout number + m_nBailout[rad] = static_cast<unsigned int> ( m_bailoutFrac[rad] * m_nPoints[rad] ); + } + + // // the ray-tracing mode + // LHCb::RichTraceMode tmpMode ( LHCb::RichTraceMode::RespectHPDTubes, + // ( m_useDetailedHPDsForRayT ? + // LHCb::RichTraceMode::SphericalHPDs : + // LHCb::RichTraceMode::FlatHPDs ) ); + // if ( m_checkBeamPipe ) { tmpMode.setBeamPipeIntersects(true); } + // m_traceModeRad[Rich::Aerogel] = tmpMode; + // m_traceModeRad[Rich::Aerogel].setAeroRefraction(true); + // m_traceModeRad[Rich::Rich1Gas] = tmpMode; + // m_traceModeRad[Rich::Rich2Gas] = tmpMode; + // _ri_debug << "Aerogel Track " << m_traceModeRad[Rich::Aerogel] << endmsg; + // _ri_debug << "Rich1Gas Track " << m_traceModeRad[Rich::Rich1Gas] << endmsg; + // _ri_debug << "Rich2Gas Track " << m_traceModeRad[Rich::Rich2Gas] << endmsg; + + // Get the CPU capabilities and set dispatch method + enum CPUID { GENERIC = 0, SSE4 = 6, AVX = 7, AVX2 = 8 }; + const auto cpuLevel = instrset_detect(); + _ri_debug << "Instruction set level = " << cpuLevel << endmsg; + if ( cpuLevel >= AVX2 ) { m_run = &RayTraceCherenkovConesSIMD::run_avx2; } + else if ( cpuLevel >= AVX ) { m_run = &RayTraceCherenkovConesSIMD::run_avx; } + else if ( cpuLevel >= SSE4 ) { m_run = &RayTraceCherenkovConesSIMD::run_sse4; } + else { m_run = &RayTraceCherenkovConesSIMD::run_generic; } + + // return + return sc; +} + +//============================================================================= + +// Declaration of the Algorithm Factory +DECLARE_ALGORITHM_FACTORY( RayTraceCherenkovConesSIMD ) + +//============================================================================= diff --git a/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovConesSIMD.h b/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovConesSIMD.h new file mode 100644 index 0000000000..ad0d403d01 --- /dev/null +++ b/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovConesSIMD.h @@ -0,0 +1,201 @@ + +#pragma once + +// Gaudi +#include "GaudiKernel/ParsersFactory.h" +#include "GaudiKernel/StdArrayAsProperty.h" +#include "GaudiAlg/Transformer.h" +#include "GaudiKernel/PhysicalConstants.h" + +// Base class +#include "RichFutureRecBase/RichRecAlgBase.h" + +// Event Model +#include "RichFutureRecEvent/RichRecCherenkovAngles.h" +#include "RichFutureRecEvent/RichRecMassHypoRings.h" + +// Utils +#include "RichUtils/RichTrackSegment.h" +#include "RichFutureUtils/RichGeomPhoton.h" +#include "RichUtils/ZipRange.h" +#include "RichUtils/RichRayTracingUtils.h" + +// Rec Utils +#include "RichRecUtils/RichRadCorrLocalPositions.h" + +// RichDet +#include "RichDet/DeRich.h" + +// Interfaces +//#include "RichFutureInterfaces/IRichRayTracing.h" +#include "RichInterfaces/IRichSmartIDTool.h" +#include "RichInterfaces/IRichMirrorSegFinderLookUpTable.h" + +// VDT +#include "vdt/sincos.h" + +// Vector Class +#include "VectorClass/instrset.h" + +// Vc +#include <Vc/Vc> + +// LHCb TemplatedGenVector +#include "TemplatedGenVector/DisplacementVector3D.h" +#include "TemplatedGenVector/PositionVector3D.h" +#include "TemplatedGenVector/Plane3D.h" + +namespace Rich +{ + namespace Future + { + + // Use the functional framework + using namespace Gaudi::Functional; + + namespace Rec + { + + /** @class RayTraceCherenkovConesSIMD RichRayTraceCherenkovConesSIMD.h + * + * Creates the Cherenkov cones for each segment and mass hypothesis, + * using photon raytracing. + * + * @author Chris Jones + * @date 2016-09-30 + */ + + class RayTraceCherenkovConesSIMD final : + public Transformer< MassHypoRingsVector( const LHCb::RichTrackSegment::Vector&, + const CherenkovAngles::Vector& ), + Traits::BaseClass_t<AlgBase> > + { + + public: + + /// Standard constructor + RayTraceCherenkovConesSIMD( const std::string& name, + ISvcLocator* pSvcLocator ); + + /// Initialization after creation + StatusCode initialize() override; + + public: + + /// Functional operator + inline MassHypoRingsVector + operator()( const LHCb::RichTrackSegment::Vector& segments, + const CherenkovAngles::Vector& ckAngles ) const override + { + return (this->*m_run)( segments, ckAngles ); + } + + private: + + /// Generic dispatch function + MassHypoRingsVector + run_generic( const LHCb::RichTrackSegment::Vector& segments, + const CherenkovAngles::Vector& ckAngles ) const; + + /// SSE4 dispatch function + MassHypoRingsVector + run_sse4( const LHCb::RichTrackSegment::Vector& segments, + const CherenkovAngles::Vector& ckAngles ) const; + + /// AVX dispatch function + MassHypoRingsVector + run_avx( const LHCb::RichTrackSegment::Vector& segments, + const CherenkovAngles::Vector& ckAngles ) const; + + /// AVX2 dispatch function + MassHypoRingsVector + run_avx2( const LHCb::RichTrackSegment::Vector& segments, + const CherenkovAngles::Vector& ckAngles ) const; + + /** Pointer to dispatch function for the operator call + * Default to lowest common denominator. + * Reset in initialize() according to runtime support */ + MassHypoRingsVector (RayTraceCherenkovConesSIMD::*m_run) + ( const LHCb::RichTrackSegment::Vector& segments, + const CherenkovAngles::Vector& ckAngles ) const + = &RayTraceCherenkovConesSIMD::run_generic; + + private: // helper classes + + /** @class CosSinPhi RichRayTraceCherenkovCone.h + * + * Utility class to cache cos and sin values + * + * @author Chris Jones Christopher.Rob.Jones@cern.ch + * @date 17/02/2008 + */ + template< typename TYPE > + class CosSinPhi + { + public: + typedef std::vector<CosSinPhi> Vector; + public: + explicit CosSinPhi( const TYPE _phi ) : phi(_phi) + { + vdt::fast_sincos( phi, sinPhi, cosPhi ); + } + public: + TYPE phi = 0; ///< CK phi + TYPE cosPhi = 0; ///< Cos(CK phi) + TYPE sinPhi = 0; ///< Sin(CK phi) + }; + + /// Vc Vector + template < typename TYPE > + using VcAllocVector = std::vector< TYPE, Vc::Allocator<TYPE> >; + + private: + + /// Rich1 and Rich2 pointers + Rich::DetectorArray<const DeRich*> m_rich{{nullptr,nullptr}}; + + /// Number of points to ray trace on each ring, for each radiator + Gaudi::Property< RadiatorArray<unsigned int> > m_nPoints + { this, "NRingPoints", { 100u, 100u, 100u } }; + + /// Bailout number + RadiatorArray<unsigned int> m_nBailout = {{}}; + + /// Cached cos and sin values around the ring, for each radiator + RadiatorArray< CosSinPhi<double>::Vector > m_cosSinPhiV; + + /// Mirror segment finder tool + ToolHandle<const IMirrorSegFinderLookUpTable> m_mirrorSegFinder + { "Rich::Future::MirrorSegFinderLookUpTable/MirrorFinder:PUBLIC", this }; + + /// Cached trace modes for each radiator + //RadiatorArray<LHCb::RichTraceMode> m_traceModeRad = {{}}; + + /// Flag to turn on or off checking of intersections with beampipe + //Gaudi::Property<bool> m_checkBeamPipe { this, "CheckBeamPipe", true }; + + /// Flag to switch between simple or detail HPD description in ray tracing + //Gaudi::Property<bool> m_useDetailedHPDsForRayT { this, "UseDetailedHPDs", false }; + + /** Bailout fraction. If no ray tracings have worked after this fraction have been + * perfromed, then give up */ + Gaudi::Property< RadiatorArray<float> > m_bailoutFrac + { this, "BailoutFraction", { 0.75, 0.75, 0.75 } }; + + /// Flag to control if the secondary mirrors are treated as if they are completely flat + Gaudi::Property< DetectorArray<bool> > m_treatSecMirrsFlat + { this, "AssumeFlatSecondaryMirrors", { true, false } }; + + /// Ray tracing tool + //ToolHandle<const IRayTracing> m_rayTrace + //{ "Rich::Future::RayTracing/RayTracing", this }; + + /// RichSmartID Tool + ToolHandle<const ISmartIDTool> m_idTool + { "Rich::Future::SmartIDTool/SmartIDTool:PUBLIC", this }; + + }; + + } + } +} diff --git a/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovConesSIMD.icpp b/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovConesSIMD.icpp new file mode 100644 index 0000000000..c5f11bb638 --- /dev/null +++ b/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovConesSIMD.icpp @@ -0,0 +1,261 @@ + +{ + + // types + using ScFloat = float; + using VcFloat = Vc::float_v; + using VcInt = Vc::int_v; + using ScInt = int; + using VcPoint = LHCbROOT::Math::PositionVector3D < LHCbROOT::Math::Cartesian3D<VcFloat> >; + using VcVector = LHCbROOT::Math::DisplacementVector3D< LHCbROOT::Math::Cartesian3D<VcFloat> >; + using VcPlane = LHCbROOT::Math::Impl::Plane3D<VcFloat>; + + // Ray tracing utils + using namespace Rich::RayTracingUtils; + + // The data to return + MassHypoRingsVector ringsV; + ringsV.reserve( segments.size() ); + + // Temporary working photon object. Need to eventually remove need for this. + GeomPhoton photon; + + // local position corrector + // longer term need to remove this + const Rich::Rec::RadPositionCorrector corrector; + + // loop over the input data + for ( const auto && data : Ranges::ConstZip(segments,ckAngles) ) + { + const auto & segment = std::get<0>(data); + const auto & ckTheta = std::get<1>(data); + + // Add a set of mass hypo rings for this segment + ringsV.emplace_back( ); + auto & rings = ringsV.back(); + + // which rich and radiator + const auto rich = segment.rich(); + const auto rad = segment.radiator(); + + // best emission point + const auto & ePnt = segment.bestPoint(); + + // Start detector side + const auto side = m_rich[rich]->side(ePnt); + + // Number of VcVector objects + const auto NVC = m_nPoints[rad] / VcFloat::Size; + + // Loop over PID types + for ( const auto id : activeParticles() ) + { + // Above threshold ? + if ( ckTheta[id] > 0 ) + { + + // compute sin and cos theta + double sinTheta(0), cosTheta(0); + vdt::fast_sincos( ckTheta[id], sinTheta, cosTheta ); + + // reserve size in the points container + rings[id].reserve( m_nPoints[rad] ); + + // Form the starting detector sides + VcAllocVector<VcInt> photSides( NVC, VcInt(side) ); + + // Form the starting points + VcAllocVector<VcPoint> startPoints( NVC, VcPoint(ePnt.x(),ePnt.y(),ePnt.z()) ); + + // Form the starting points and directions. + VcAllocVector<VcVector> startDirs; + // Will be able to vectorise this better once GenVector in ROOT has my updates + { + unsigned int nPhot(0); + // Vc vectors for (x,y,z) + VcFloat x,y,z; + for ( auto iP = m_cosSinPhiV[rad].begin(); iP != m_cosSinPhiV[rad].end(); ++iP, ++nPhot ) + { + // Vc index + const auto ivc = nPhot % VcFloat::Size; + // Photon direction around loop + const auto photDir = + segment.vectorAtCosSinThetaPhi( cosTheta, sinTheta, + (*iP).cosPhi, (*iP).sinPhi ); + // Fill Vc words + x[ivc] = photDir.x(); + y[ivc] = photDir.y(); + z[ivc] = photDir.z(); + // If last index, make a new entry in the vector and fill + if ( VcFloat::Size-1 == ivc ) { startDirs.emplace_back(x,y,z); } + } + } + + // Starting CoC values + VcAllocVector<VcPoint> CoCs( NVC, VcPoint( m_rich[rich]->nominalCentreOfCurvature(side) ) ); + + // Starting RoC values + VcAllocVector<VcFloat> RoCs( NVC, VcFloat( m_rich[rich]->sphMirrorRadius() ) ); + + // Intersect with the spherical mirrors to find the reflection points and use these + // to find the mirror segments to use for the primary mirrors + for ( auto && data : Ranges::Zip(startPoints,startDirs,CoCs,RoCs,photSides) ) + { + auto & startP = std::get<0>(data); + auto & startD = std::get<1>(data); + auto & CoC = std::get<2>(data); + auto & RoC = std::get<3>(data); + auto & sides = std::get<4>(data); + + // interset with nominal primary + VcPoint nomSphInter; + auto mask = intersectSpherical( startP, startD, CoC, RoC, nomSphInter ); + if ( any_of(mask) ) + { + + // Check if we are on the same detector side or not + VcInt newSides(sides); + // To Do - Fix RichDet Vc support + //m_rich[rich]->sides( nomSphInter, newSides ); + { + VcFloat x(CoC.x()), y(CoC.y()), z(CoC.z()); + for ( std::size_t i = 0; i < VcFloat::Size; ++i ) + { + // Check the detector side for the intersection point + const auto nside = m_rich[rich]->side( (ScFloat)nomSphInter.x()[i], + (ScFloat)nomSphInter.y()[i] ); + newSides[i] = ScInt( nside ); + if ( newSides[i] != sides[i] ) + { + // Update CoC and RoC for this entry + const auto& nCoC = m_rich[rich]->nominalCentreOfCurvature(nside); + x[i] = nCoC.x(); + y[i] = nCoC.y(); + z[i] = nCoC.z(); + RoC[i] = m_rich[rich]->sphMirrorRadius(); + } + } + // Update the CoC point + CoC = VcPoint(x,y,z); + } + // if any think changed rerun the intersection + if ( UNLIKELY( any_of( sides != newSides ) ) ) + { + sides = newSides; + mask &= intersectSpherical( startP, startD, CoC, RoC, nomSphInter ); + } + + if ( any_of(mask) ) + { + + { + // Copy the CoC parameters + VcFloat x(CoC.x()), y(CoC.y()), z(CoC.z()); + // Find primary mirror segments to update CoC and RoC foreach photon + for ( std::size_t i = 0; i < VcFloat::Size; ++i ) + { + // Find the primary mirror segment for this point + const auto * sphSegment = + m_mirrorSegFinder.get()->findSphMirror( rich, side, + (ScFloat)nomSphInter.x()[i], + (ScFloat)nomSphInter.y()[i] ); + // update the mirror parameters + const auto& nCoC = sphSegment->centreOfCurvature(); + x[i] = nCoC.x(); + y[i] = nCoC.y(); + z[i] = nCoC.z(); + RoC[i] = sphSegment->radius(); + } + // Update the CoC point + CoC = VcPoint(x,y,z); + } + + // perform the final reflection on the primaries + mask &= reflectSpherical( startP, startD, CoC, RoC ); + + if ( any_of(mask) ) + { + // move on to the secondary mirrors + + // nominal intersection point + VcPoint planeInt; + const auto& plane = m_rich[rich]->nominalPlane(side); + VcPlane vcplane( plane.A(), plane.B(), plane.C(), plane.D() ); + mask &= intersectPlane( startP, startD, vcplane, planeInt ); + + if ( any_of(mask) ) + { + // Find the exact secondary mirror segments + + // Copy the nominal plane parameters + auto A(vcplane.A()), B(vcplane.B()), C(vcplane.C()), D(vcplane.D()); + // Copy the CoC parameters + VcFloat x(CoC.x()), y(CoC.y()), z(CoC.z()); + for ( std::size_t i = 0; i < VcFloat::Size; ++i ) + { + // find secondary mirror segment + const auto * secSegment = + m_mirrorSegFinder.get()->findSecMirror( rich, side, + (ScFloat)planeInt.x()[i], + (ScFloat)planeInt.y()[i] ); + // flat versus spherical treatment + if ( m_treatSecMirrsFlat[rich] ) + { + // Update the normal plane + const auto & npl = secSegment->centreNormalPlane(); + A[i] = npl.A(); + B[i] = npl.B(); + C[i] = npl.C(); + D[i] = npl.D(); + } + else + { + // update speherical parameters for the secondary mirrors + const auto& nCoC = secSegment->centreOfCurvature(); + x[i] = nCoC.x(); + y[i] = nCoC.y(); + z[i] = nCoC.z(); + RoC[i] = secSegment->radius(); + } + } + + // reflect off the secondary mirrors + mask &= ( m_treatSecMirrsFlat[rich] ? + reflectPlane ( startP, startD, VcPlane(A,B,C,D) ) : + reflectSpherical( startP, startD, VcPoint(x,y,z), RoC ) ); + + + // If OK, proceed to getting the hit position + if ( any_of(mask) ) + { + + + + + + + } + + } + + } + + } + + } // first intersection ok + + } // loop over photons + + + + + + + } + + } + + } + + return ringsV; +} diff --git a/Rich/RichFutureRecTrackAlgorithms/src/avx/RichRayTraceCherenkovCones.cpp b/Rich/RichFutureRecTrackAlgorithms/src/avx/RichRayTraceCherenkovCones.cpp new file mode 100644 index 0000000000..067b58c58b --- /dev/null +++ b/Rich/RichFutureRecTrackAlgorithms/src/avx/RichRayTraceCherenkovCones.cpp @@ -0,0 +1,14 @@ + +// local +#include "../RichRayTraceCherenkovConesSIMD.h" + +// All code is in general Rich reconstruction namespace +using namespace Rich::Future::Rec; + +MassHypoRingsVector +RayTraceCherenkovConesSIMD:: +run_avx( const LHCb::RichTrackSegment::Vector& segments, + const CherenkovAngles::Vector& ckAngles ) const +{ +#include "../RichRayTraceCherenkovConesSIMD.icpp" +} diff --git a/Rich/RichFutureRecTrackAlgorithms/src/avx2/RichRayTraceCherenkovCones.cpp b/Rich/RichFutureRecTrackAlgorithms/src/avx2/RichRayTraceCherenkovCones.cpp new file mode 100644 index 0000000000..f7db884820 --- /dev/null +++ b/Rich/RichFutureRecTrackAlgorithms/src/avx2/RichRayTraceCherenkovCones.cpp @@ -0,0 +1,14 @@ + +// local +#include "../RichRayTraceCherenkovConesSIMD.h" + +// All code is in general Rich reconstruction namespace +using namespace Rich::Future::Rec; + +MassHypoRingsVector +RayTraceCherenkovConesSIMD:: +run_avx2( const LHCb::RichTrackSegment::Vector& segments, + const CherenkovAngles::Vector& ckAngles ) const +{ +#include "../RichRayTraceCherenkovConesSIMD.icpp" +} diff --git a/Rich/RichFutureRecTrackAlgorithms/src/generic/RichRayTraceCherenkovCones.cpp b/Rich/RichFutureRecTrackAlgorithms/src/generic/RichRayTraceCherenkovCones.cpp new file mode 100644 index 0000000000..311c28b8d8 --- /dev/null +++ b/Rich/RichFutureRecTrackAlgorithms/src/generic/RichRayTraceCherenkovCones.cpp @@ -0,0 +1,14 @@ + +// local +#include "../RichRayTraceCherenkovConesSIMD.h" + +// All code is in general Rich reconstruction namespace +using namespace Rich::Future::Rec; + +MassHypoRingsVector +RayTraceCherenkovConesSIMD:: +run_generic( const LHCb::RichTrackSegment::Vector& segments, + const CherenkovAngles::Vector& ckAngles ) const +{ +#include "../RichRayTraceCherenkovConesSIMD.icpp" +} diff --git a/Rich/RichFutureRecTrackAlgorithms/src/sse4/RichRayTraceCherenkovCones.cpp b/Rich/RichFutureRecTrackAlgorithms/src/sse4/RichRayTraceCherenkovCones.cpp new file mode 100644 index 0000000000..4b59308297 --- /dev/null +++ b/Rich/RichFutureRecTrackAlgorithms/src/sse4/RichRayTraceCherenkovCones.cpp @@ -0,0 +1,14 @@ + +// local +#include "../RichRayTraceCherenkovConesSIMD.h" + +// All code is in general Rich reconstruction namespace +using namespace Rich::Future::Rec; + +MassHypoRingsVector +RayTraceCherenkovConesSIMD:: +run_sse4( const LHCb::RichTrackSegment::Vector& segments, + const CherenkovAngles::Vector& ckAngles ) const +{ +#include "../RichRayTraceCherenkovConesSIMD.icpp" +} diff --git a/Rich/RichRecTests/CMakeLists.txt b/Rich/RichRecTests/CMakeLists.txt index 88264c4108..a227c20223 100644 --- a/Rich/RichRecTests/CMakeLists.txt +++ b/Rich/RichRecTests/CMakeLists.txt @@ -8,6 +8,7 @@ gaudi_depends_on_subdirs(Det/RichDet Kernel/LHCbKernel Kernel/LHCbMath Kernel/VectorClass + Kernel/TemplatedGenVector Kernel/Vc Rich/RichRecUtils) @@ -16,7 +17,7 @@ find_package(Boost) find_package(GSL) find_package(Eigen) find_package(Vc) -find_package(ROOT COMPONENTS MathCore GenVector) +find_package(ROOT COMPONENTS MathCore GenVector ) message(STATUS "Using Vc ${Vc_INCLUDE_DIR} ${Vc_LIB_DIR}") message(STATUS "Vc DEFINITIONS ${Vc_DEFINITIONS}") @@ -30,29 +31,29 @@ if(GAUDI_BUILD_TESTS) gaudi_add_executable(RichPhotonRecoTestSSE4 src/PhotonReco/main_sse4.cpp - INCLUDE_DIRS ROOT Vc Eigen GSL VectorClass src - LINK_LIBRARIES LHCbMathLib GSL GaudiKernel) + INCLUDE_DIRS Kernel/TemplatedGenVector ROOT Vc Eigen GSL VectorClass src + LINK_LIBRARIES LHCbMathLib GSL GaudiKernel TemplatedGenVectorLib ) target_link_libraries( RichPhotonRecoTestSSE4 -lrt ) set_property(SOURCE src/RayTracing/main_sse4.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -msse4.2 " ) gaudi_add_executable(RichPhotonRecoTestAVX src/PhotonReco/main_avx.cpp - INCLUDE_DIRS ROOT Vc Eigen GSL VectorClass src - LINK_LIBRARIES LHCbMathLib GSL GaudiKernel) + INCLUDE_DIRS Kernel/TemplatedGenVector ROOT Vc Eigen GSL VectorClass src + LINK_LIBRARIES LHCbMathLib GSL GaudiKernel TemplatedGenVectorLib ) target_link_libraries( RichPhotonRecoTestAVX -lrt ) set_property(SOURCE src/RayTracing/main_avx.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -mavx -fabi-version=0 -fabi-compat-version=0 -ffp-contract=fast " ) gaudi_add_executable(RichPhotonRecoTestAVX2 src/PhotonReco/main_avx2.cpp - INCLUDE_DIRS ROOT Vc Eigen GSL VectorClass src - LINK_LIBRARIES LHCbMathLib GSL GaudiKernel) + INCLUDE_DIRS Kernel/TemplatedGenVector ROOT Vc Eigen GSL VectorClass src + LINK_LIBRARIES LHCbMathLib GSL GaudiKernel TemplatedGenVectorLib ) target_link_libraries( RichPhotonRecoTestAVX2 -lrt ) set_property(SOURCE src/RayTracing/main_avx2.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -mavx2 -fabi-version=0 -fabi-compat-version=0 -ffp-contract=fast " ) gaudi_add_executable(RichPhotonRecoTestAVX2FMA src/PhotonReco/main_avx2fma.cpp - INCLUDE_DIRS ROOT Vc Eigen GSL VectorClass src - LINK_LIBRARIES LHCbMathLib GSL GaudiKernel) + INCLUDE_DIRS Kernel/TemplatedGenVector ROOT Vc Eigen GSL VectorClass src + LINK_LIBRARIES LHCbMathLib GSL GaudiKernel TemplatedGenVectorLib ) target_link_libraries( RichPhotonRecoTestAVX2FMA -lrt ) set_property(SOURCE src/RayTracing/main_avx2fma.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -mfma -mavx2 -fabi-version=0 -fabi-compat-version=0 -ffp-contract=fast " ) @@ -60,29 +61,29 @@ if(GAUDI_BUILD_TESTS) gaudi_add_executable(RichRayTracingTestSSE4 src/RayTracing/main_sse4.cpp - INCLUDE_DIRS ROOT Vc Eigen GSL VectorClass src - LINK_LIBRARIES LHCbMathLib GSL GaudiKernel) + INCLUDE_DIRS Kernel/TemplatedGenVector ROOT Vc Eigen GSL VectorClass src + LINK_LIBRARIES LHCbMathLib GSL GaudiKernel TemplatedGenVectorLib ) target_link_libraries( RichRayTracingTestSSE4 "-lrt ${Vc_LIB_DIR}/libVc.a" ) set_property(SOURCE src/RayTracing/main_sse4.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-ignored-attributes -msse4.2 " ) gaudi_add_executable(RichRayTracingTestAVX src/RayTracing/main_avx.cpp - INCLUDE_DIRS ROOT Vc Eigen GSL VectorClass src - LINK_LIBRARIES LHCbMathLib GSL GaudiKernel) + INCLUDE_DIRS Kernel/TemplatedGenVector ROOT Vc Eigen GSL VectorClass src + LINK_LIBRARIES LHCbMathLib GSL GaudiKernel TemplatedGenVectorLib ) target_link_libraries( RichRayTracingTestAVX "-lrt ${Vc_LIB_DIR}/libVc.a" ) set_property(SOURCE src/RayTracing/main_avx.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-ignored-attributes -mavx -fabi-version=0 -fabi-compat-version=0 -ffp-contract=fast " ) gaudi_add_executable(RichRayTracingTestAVX2 src/RayTracing/main_avx2.cpp - INCLUDE_DIRS ROOT Vc Eigen GSL VectorClass src - LINK_LIBRARIES LHCbMathLib GSL GaudiKernel) + INCLUDE_DIRS Kernel/TemplatedGenVector ROOT Vc Eigen GSL VectorClass src + LINK_LIBRARIES LHCbMathLib GSL GaudiKernel TemplatedGenVectorLib ) target_link_libraries( RichRayTracingTestAVX2 "-lrt ${Vc_LIB_DIR}/libVc.a" ) set_property(SOURCE src/RayTracing/main_avx2.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-ignored-attributes -mavx2 -fabi-version=0 -fabi-compat-version=0 -ffp-contract=fast " ) gaudi_add_executable(RichRayTracingTestAVX2FMA src/RayTracing/main_avx2fma.cpp - INCLUDE_DIRS ROOT Vc Eigen GSL VectorClass src - LINK_LIBRARIES LHCbMathLib GSL GaudiKernel) + INCLUDE_DIRS Kernel/TemplatedGenVector ROOT Vc Eigen GSL VectorClass src + LINK_LIBRARIES LHCbMathLib GSL GaudiKernel TemplatedGenVectorLib ) target_link_libraries( RichRayTracingTestAVX2FMA "-lrt ${Vc_LIB_DIR}/libVc.a" ) set_property(SOURCE src/RayTracing/main_avx2fma.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-ignored-attributes -mfma -mavx2 -fabi-version=0 -fabi-compat-version=0 -ffp-contract=fast " ) diff --git a/Rich/RichRecTests/src/RayTracing/main.icpp b/Rich/RichRecTests/src/RayTracing/main.icpp index 8f446edfb7..802a83b2b7 100644 --- a/Rich/RichRecTests/src/RayTracing/main.icpp +++ b/Rich/RichRecTests/src/RayTracing/main.icpp @@ -77,6 +77,7 @@ inline void trace( DATA & dataV ) { reflectSpherical( data.position, data.direction, data.CoC, data.radius ); reflectPlane ( data.position, data.direction, data.plane ); + std::cout << data.position << std::endl; } } @@ -88,10 +89,12 @@ unsigned long long int __attribute__((noinline)) rayTrace( const DATA & in_dataV unsigned long long int best_dur{ 99999999999999999 }; - const unsigned int nTests = 10000; + const unsigned int nTests = 1; + std::cout << "Running " << nTests << " tests on " << in_dataV.size() << " data objects" << std::endl; + DATA dataV; // working data copy; for ( unsigned int i = 0; i < nTests; ++i ) { - auto dataV = in_dataV; // copy data, as it will be modified + dataV = in_dataV; // copy data, as it will be modified clock_gettime(CLOCK_MONOTONIC_RAW,&start); trace( dataV ); clock_gettime(CLOCK_MONOTONIC_RAW,&end); @@ -105,8 +108,8 @@ unsigned long long int __attribute__((noinline)) rayTrace( const DATA & in_dataV int main ( int /*argc*/, char** /*argv*/ ) { - const unsigned int nPhotons = 96 * 1e2; - //const unsigned int nPhotons = 8; + //const unsigned int nPhotons = 96 * 1e2; + const unsigned int nPhotons = 8; std::cout << "Creating " << nPhotons << " random photons ..." << std::endl; // Templated GenVector @@ -114,16 +117,16 @@ int main ( int /*argc*/, char** /*argv*/ ) using LHCbXYZVectorD = LHCbROOT::Math::DisplacementVector3D<LHCbROOT::Math::Cartesian3D<double>,LHCbROOT::Math::DefaultCoordinateSystemTag>; using LHCbXYZPointF = LHCbROOT::Math::PositionVector3D<LHCbROOT::Math::Cartesian3D<float>,LHCbROOT::Math::DefaultCoordinateSystemTag>; using LHCbXYZVectorF = LHCbROOT::Math::DisplacementVector3D<LHCbROOT::Math::Cartesian3D<float>,LHCbROOT::Math::DefaultCoordinateSystemTag>; - using LHCbPlane3DD = LHCbROOT::Math::Plane3D<double>; - using LHCbPlane3DF = LHCbROOT::Math::Plane3D<float>; + using LHCbPlane3DD = LHCbROOT::Math::Impl::Plane3D<double>; + using LHCbPlane3DF = LHCbROOT::Math::Impl::Plane3D<float>; // Vc using VcXYZPointD = LHCbROOT::Math::PositionVector3D<LHCbROOT::Math::Cartesian3D<Vc::double_v>,LHCbROOT::Math::DefaultCoordinateSystemTag>; using VcXYZVectorD = LHCbROOT::Math::DisplacementVector3D<LHCbROOT::Math::Cartesian3D<Vc::double_v>,LHCbROOT::Math::DefaultCoordinateSystemTag>; using VcXYZPointF = LHCbROOT::Math::PositionVector3D<LHCbROOT::Math::Cartesian3D<Vc::float_v>,LHCbROOT::Math::DefaultCoordinateSystemTag>; using VcXYZVectorF = LHCbROOT::Math::DisplacementVector3D<LHCbROOT::Math::Cartesian3D<Vc::float_v>,LHCbROOT::Math::DefaultCoordinateSystemTag>; - using VcPlane3DD = LHCbROOT::Math::Plane3D<Vc::double_v>; - using VcPlane3DF = LHCbROOT::Math::Plane3D<Vc::float_v>; + using VcPlane3DD = LHCbROOT::Math::Impl::Plane3D<Vc::double_v>; + using VcPlane3DF = LHCbROOT::Math::Impl::Plane3D<Vc::float_v>; //if ( false ) { -- GitLab From a7d91483f5f313a6a5b0f7c9f641d10a190ccdbe Mon Sep 17 00:00:00 2001 From: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Thu, 2 Mar 2017 00:12:18 +0100 Subject: [PATCH 27/68] remove unused features --- .../src/RichRayTraceCherenkovConesSIMD.cpp | 15 ------------- .../src/RichRayTraceCherenkovConesSIMD.h | 22 ++++--------------- .../src/RichRayTraceCherenkovConesSIMD.icpp | 4 ---- 3 files changed, 4 insertions(+), 37 deletions(-) diff --git a/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovConesSIMD.cpp b/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovConesSIMD.cpp index f73429cae1..bbcb2f5cd1 100644 --- a/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovConesSIMD.cpp +++ b/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovConesSIMD.cpp @@ -14,7 +14,6 @@ RayTraceCherenkovConesSIMD::RayTraceCherenkovConesSIMD( const std::string& name, KeyValue{ "CherenkovAnglesLocation", CherenkovAnglesLocation::Emitted } }, { KeyValue{ "MassHypothesisRingsLocation", MassHypoRingsLocation::Emitted } } ) { - //declareProperty( "RayTracingTool", m_rayTrace ); // debugging //setProperty( "OutputLevel", MSG::VERBOSE ); } @@ -55,20 +54,6 @@ StatusCode RayTraceCherenkovConesSIMD::initialize() m_nBailout[rad] = static_cast<unsigned int> ( m_bailoutFrac[rad] * m_nPoints[rad] ); } - // // the ray-tracing mode - // LHCb::RichTraceMode tmpMode ( LHCb::RichTraceMode::RespectHPDTubes, - // ( m_useDetailedHPDsForRayT ? - // LHCb::RichTraceMode::SphericalHPDs : - // LHCb::RichTraceMode::FlatHPDs ) ); - // if ( m_checkBeamPipe ) { tmpMode.setBeamPipeIntersects(true); } - // m_traceModeRad[Rich::Aerogel] = tmpMode; - // m_traceModeRad[Rich::Aerogel].setAeroRefraction(true); - // m_traceModeRad[Rich::Rich1Gas] = tmpMode; - // m_traceModeRad[Rich::Rich2Gas] = tmpMode; - // _ri_debug << "Aerogel Track " << m_traceModeRad[Rich::Aerogel] << endmsg; - // _ri_debug << "Rich1Gas Track " << m_traceModeRad[Rich::Rich1Gas] << endmsg; - // _ri_debug << "Rich2Gas Track " << m_traceModeRad[Rich::Rich2Gas] << endmsg; - // Get the CPU capabilities and set dispatch method enum CPUID { GENERIC = 0, SSE4 = 6, AVX = 7, AVX2 = 8 }; const auto cpuLevel = instrset_detect(); diff --git a/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovConesSIMD.h b/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovConesSIMD.h index ad0d403d01..5284a5a7ee 100644 --- a/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovConesSIMD.h +++ b/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovConesSIMD.h @@ -27,7 +27,6 @@ #include "RichDet/DeRich.h" // Interfaces -//#include "RichFutureInterfaces/IRichRayTracing.h" #include "RichInterfaces/IRichSmartIDTool.h" #include "RichInterfaces/IRichMirrorSegFinderLookUpTable.h" @@ -156,10 +155,10 @@ namespace Rich /// Number of points to ray trace on each ring, for each radiator Gaudi::Property< RadiatorArray<unsigned int> > m_nPoints - { this, "NRingPoints", { 100u, 100u, 100u } }; + { this, "NRingPoints", { 96u, 96u, 96u } }; /// Bailout number - RadiatorArray<unsigned int> m_nBailout = {{}}; + //RadiatorArray<unsigned int> m_nBailout = {{}}; /// Cached cos and sin values around the ring, for each radiator RadiatorArray< CosSinPhi<double>::Vector > m_cosSinPhiV; @@ -168,28 +167,15 @@ namespace Rich ToolHandle<const IMirrorSegFinderLookUpTable> m_mirrorSegFinder { "Rich::Future::MirrorSegFinderLookUpTable/MirrorFinder:PUBLIC", this }; - /// Cached trace modes for each radiator - //RadiatorArray<LHCb::RichTraceMode> m_traceModeRad = {{}}; - - /// Flag to turn on or off checking of intersections with beampipe - //Gaudi::Property<bool> m_checkBeamPipe { this, "CheckBeamPipe", true }; - - /// Flag to switch between simple or detail HPD description in ray tracing - //Gaudi::Property<bool> m_useDetailedHPDsForRayT { this, "UseDetailedHPDs", false }; - /** Bailout fraction. If no ray tracings have worked after this fraction have been * perfromed, then give up */ - Gaudi::Property< RadiatorArray<float> > m_bailoutFrac - { this, "BailoutFraction", { 0.75, 0.75, 0.75 } }; + //Gaudi::Property< RadiatorArray<float> > m_bailoutFrac + //{ this, "BailoutFraction", { 0.75, 0.75, 0.75 } }; /// Flag to control if the secondary mirrors are treated as if they are completely flat Gaudi::Property< DetectorArray<bool> > m_treatSecMirrsFlat { this, "AssumeFlatSecondaryMirrors", { true, false } }; - /// Ray tracing tool - //ToolHandle<const IRayTracing> m_rayTrace - //{ "Rich::Future::RayTracing/RayTracing", this }; - /// RichSmartID Tool ToolHandle<const ISmartIDTool> m_idTool { "Rich::Future::SmartIDTool/SmartIDTool:PUBLIC", this }; diff --git a/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovConesSIMD.icpp b/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovConesSIMD.icpp index c5f11bb638..339693b184 100644 --- a/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovConesSIMD.icpp +++ b/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovConesSIMD.icpp @@ -246,10 +246,6 @@ } // loop over photons - - - - } -- GitLab From 95bb3ebfd903eaddc755dd525acd4e83a33bb23b Mon Sep 17 00:00:00 2001 From: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Thu, 2 Mar 2017 00:20:35 +0100 Subject: [PATCH 28/68] remove unused features --- .../src/RichRayTraceCherenkovConesSIMD.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovConesSIMD.cpp b/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovConesSIMD.cpp index bbcb2f5cd1..d8b5571d91 100644 --- a/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovConesSIMD.cpp +++ b/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovConesSIMD.cpp @@ -51,7 +51,7 @@ StatusCode RayTraceCherenkovConesSIMD::initialize() for ( unsigned int iPhot = 0; iPhot < m_nPoints[rad]; ++iPhot, ckPhi+=incPhi ) { m_cosSinPhiV[rad].emplace_back( ckPhi ); } // bailout number - m_nBailout[rad] = static_cast<unsigned int> ( m_bailoutFrac[rad] * m_nPoints[rad] ); + //m_nBailout[rad] = static_cast<unsigned int> ( m_bailoutFrac[rad] * m_nPoints[rad] ); } // Get the CPU capabilities and set dispatch method -- GitLab From a7305554fce429feef8c00525dcb61405d82aaba Mon Sep 17 00:00:00 2001 From: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Sat, 4 Mar 2017 11:37:30 +0100 Subject: [PATCH 29/68] Remove SIMD CK cone ray tracing algorithm. Vectorised ray tracing moved to RichFutureTools. --- .../src/RichRayTraceCherenkovConesSIMD.cpp | 75 ----- .../src/RichRayTraceCherenkovConesSIMD.h | 187 ------------- .../src/RichRayTraceCherenkovConesSIMD.icpp | 257 ------------------ .../src/avx/RichRayTraceCherenkovCones.cpp | 14 - .../src/avx2/RichRayTraceCherenkovCones.cpp | 14 - .../generic/RichRayTraceCherenkovCones.cpp | 14 - .../src/sse4/RichRayTraceCherenkovCones.cpp | 14 - 7 files changed, 575 deletions(-) delete mode 100644 Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovConesSIMD.cpp delete mode 100644 Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovConesSIMD.h delete mode 100644 Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovConesSIMD.icpp delete mode 100644 Rich/RichFutureRecTrackAlgorithms/src/avx/RichRayTraceCherenkovCones.cpp delete mode 100644 Rich/RichFutureRecTrackAlgorithms/src/avx2/RichRayTraceCherenkovCones.cpp delete mode 100644 Rich/RichFutureRecTrackAlgorithms/src/generic/RichRayTraceCherenkovCones.cpp delete mode 100644 Rich/RichFutureRecTrackAlgorithms/src/sse4/RichRayTraceCherenkovCones.cpp diff --git a/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovConesSIMD.cpp b/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovConesSIMD.cpp deleted file mode 100644 index d8b5571d91..0000000000 --- a/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovConesSIMD.cpp +++ /dev/null @@ -1,75 +0,0 @@ - -// local -#include "RichRayTraceCherenkovConesSIMD.h" - -// All code is in general Rich reconstruction namespace -using namespace Rich::Future::Rec; - -//============================================================================= - -RayTraceCherenkovConesSIMD::RayTraceCherenkovConesSIMD( const std::string& name, - ISvcLocator* pSvcLocator ) - : Transformer ( name, pSvcLocator, - { KeyValue{ "TrackSegmentsLocation", LHCb::RichTrackSegmentLocation::Default }, - KeyValue{ "CherenkovAnglesLocation", CherenkovAnglesLocation::Emitted } }, - { KeyValue{ "MassHypothesisRingsLocation", MassHypoRingsLocation::Emitted } } ) -{ - // debugging - //setProperty( "OutputLevel", MSG::VERBOSE ); -} - -//============================================================================= - -StatusCode RayTraceCherenkovConesSIMD::initialize() -{ - // Sets up various tools and services - auto sc = Transformer::initialize(); - if ( !sc ) return sc; - - // load tools - //sc = sc && m_rayTrace.retrieve(); - sc = sc && m_idTool.retrieve(); - sc = sc && m_mirrorSegFinder.retrieve(); - - // RICH detector elements - m_rich[Rich::Rich1] = getDet<DeRich>( DeRichLocations::Rich1 ); - m_rich[Rich::Rich2] = getDet<DeRich>( DeRichLocations::Rich2 ); - - // loop over radiators - for ( const auto rad : Rich::radiators() ) - { - // Check # photon is exactly divisible by 8 (for SIMD vectors without padding) - if ( m_nPoints[rad] % 8 != 0 ) - { - return Error( "# photons must be a multiple of 8 to avoid need for SIMD padding" ); - } - // Fill cos and sin values - m_cosSinPhiV[rad].clear(); - m_cosSinPhiV[rad].reserve( m_nPoints[rad] ); - const auto incPhi = Gaudi::Units::twopi / static_cast<double>(m_nPoints[rad]); - double ckPhi = 0.0; - for ( unsigned int iPhot = 0; iPhot < m_nPoints[rad]; ++iPhot, ckPhi+=incPhi ) - { m_cosSinPhiV[rad].emplace_back( ckPhi ); } - // bailout number - //m_nBailout[rad] = static_cast<unsigned int> ( m_bailoutFrac[rad] * m_nPoints[rad] ); - } - - // Get the CPU capabilities and set dispatch method - enum CPUID { GENERIC = 0, SSE4 = 6, AVX = 7, AVX2 = 8 }; - const auto cpuLevel = instrset_detect(); - _ri_debug << "Instruction set level = " << cpuLevel << endmsg; - if ( cpuLevel >= AVX2 ) { m_run = &RayTraceCherenkovConesSIMD::run_avx2; } - else if ( cpuLevel >= AVX ) { m_run = &RayTraceCherenkovConesSIMD::run_avx; } - else if ( cpuLevel >= SSE4 ) { m_run = &RayTraceCherenkovConesSIMD::run_sse4; } - else { m_run = &RayTraceCherenkovConesSIMD::run_generic; } - - // return - return sc; -} - -//============================================================================= - -// Declaration of the Algorithm Factory -DECLARE_ALGORITHM_FACTORY( RayTraceCherenkovConesSIMD ) - -//============================================================================= diff --git a/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovConesSIMD.h b/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovConesSIMD.h deleted file mode 100644 index 5284a5a7ee..0000000000 --- a/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovConesSIMD.h +++ /dev/null @@ -1,187 +0,0 @@ - -#pragma once - -// Gaudi -#include "GaudiKernel/ParsersFactory.h" -#include "GaudiKernel/StdArrayAsProperty.h" -#include "GaudiAlg/Transformer.h" -#include "GaudiKernel/PhysicalConstants.h" - -// Base class -#include "RichFutureRecBase/RichRecAlgBase.h" - -// Event Model -#include "RichFutureRecEvent/RichRecCherenkovAngles.h" -#include "RichFutureRecEvent/RichRecMassHypoRings.h" - -// Utils -#include "RichUtils/RichTrackSegment.h" -#include "RichFutureUtils/RichGeomPhoton.h" -#include "RichUtils/ZipRange.h" -#include "RichUtils/RichRayTracingUtils.h" - -// Rec Utils -#include "RichRecUtils/RichRadCorrLocalPositions.h" - -// RichDet -#include "RichDet/DeRich.h" - -// Interfaces -#include "RichInterfaces/IRichSmartIDTool.h" -#include "RichInterfaces/IRichMirrorSegFinderLookUpTable.h" - -// VDT -#include "vdt/sincos.h" - -// Vector Class -#include "VectorClass/instrset.h" - -// Vc -#include <Vc/Vc> - -// LHCb TemplatedGenVector -#include "TemplatedGenVector/DisplacementVector3D.h" -#include "TemplatedGenVector/PositionVector3D.h" -#include "TemplatedGenVector/Plane3D.h" - -namespace Rich -{ - namespace Future - { - - // Use the functional framework - using namespace Gaudi::Functional; - - namespace Rec - { - - /** @class RayTraceCherenkovConesSIMD RichRayTraceCherenkovConesSIMD.h - * - * Creates the Cherenkov cones for each segment and mass hypothesis, - * using photon raytracing. - * - * @author Chris Jones - * @date 2016-09-30 - */ - - class RayTraceCherenkovConesSIMD final : - public Transformer< MassHypoRingsVector( const LHCb::RichTrackSegment::Vector&, - const CherenkovAngles::Vector& ), - Traits::BaseClass_t<AlgBase> > - { - - public: - - /// Standard constructor - RayTraceCherenkovConesSIMD( const std::string& name, - ISvcLocator* pSvcLocator ); - - /// Initialization after creation - StatusCode initialize() override; - - public: - - /// Functional operator - inline MassHypoRingsVector - operator()( const LHCb::RichTrackSegment::Vector& segments, - const CherenkovAngles::Vector& ckAngles ) const override - { - return (this->*m_run)( segments, ckAngles ); - } - - private: - - /// Generic dispatch function - MassHypoRingsVector - run_generic( const LHCb::RichTrackSegment::Vector& segments, - const CherenkovAngles::Vector& ckAngles ) const; - - /// SSE4 dispatch function - MassHypoRingsVector - run_sse4( const LHCb::RichTrackSegment::Vector& segments, - const CherenkovAngles::Vector& ckAngles ) const; - - /// AVX dispatch function - MassHypoRingsVector - run_avx( const LHCb::RichTrackSegment::Vector& segments, - const CherenkovAngles::Vector& ckAngles ) const; - - /// AVX2 dispatch function - MassHypoRingsVector - run_avx2( const LHCb::RichTrackSegment::Vector& segments, - const CherenkovAngles::Vector& ckAngles ) const; - - /** Pointer to dispatch function for the operator call - * Default to lowest common denominator. - * Reset in initialize() according to runtime support */ - MassHypoRingsVector (RayTraceCherenkovConesSIMD::*m_run) - ( const LHCb::RichTrackSegment::Vector& segments, - const CherenkovAngles::Vector& ckAngles ) const - = &RayTraceCherenkovConesSIMD::run_generic; - - private: // helper classes - - /** @class CosSinPhi RichRayTraceCherenkovCone.h - * - * Utility class to cache cos and sin values - * - * @author Chris Jones Christopher.Rob.Jones@cern.ch - * @date 17/02/2008 - */ - template< typename TYPE > - class CosSinPhi - { - public: - typedef std::vector<CosSinPhi> Vector; - public: - explicit CosSinPhi( const TYPE _phi ) : phi(_phi) - { - vdt::fast_sincos( phi, sinPhi, cosPhi ); - } - public: - TYPE phi = 0; ///< CK phi - TYPE cosPhi = 0; ///< Cos(CK phi) - TYPE sinPhi = 0; ///< Sin(CK phi) - }; - - /// Vc Vector - template < typename TYPE > - using VcAllocVector = std::vector< TYPE, Vc::Allocator<TYPE> >; - - private: - - /// Rich1 and Rich2 pointers - Rich::DetectorArray<const DeRich*> m_rich{{nullptr,nullptr}}; - - /// Number of points to ray trace on each ring, for each radiator - Gaudi::Property< RadiatorArray<unsigned int> > m_nPoints - { this, "NRingPoints", { 96u, 96u, 96u } }; - - /// Bailout number - //RadiatorArray<unsigned int> m_nBailout = {{}}; - - /// Cached cos and sin values around the ring, for each radiator - RadiatorArray< CosSinPhi<double>::Vector > m_cosSinPhiV; - - /// Mirror segment finder tool - ToolHandle<const IMirrorSegFinderLookUpTable> m_mirrorSegFinder - { "Rich::Future::MirrorSegFinderLookUpTable/MirrorFinder:PUBLIC", this }; - - /** Bailout fraction. If no ray tracings have worked after this fraction have been - * perfromed, then give up */ - //Gaudi::Property< RadiatorArray<float> > m_bailoutFrac - //{ this, "BailoutFraction", { 0.75, 0.75, 0.75 } }; - - /// Flag to control if the secondary mirrors are treated as if they are completely flat - Gaudi::Property< DetectorArray<bool> > m_treatSecMirrsFlat - { this, "AssumeFlatSecondaryMirrors", { true, false } }; - - /// RichSmartID Tool - ToolHandle<const ISmartIDTool> m_idTool - { "Rich::Future::SmartIDTool/SmartIDTool:PUBLIC", this }; - - }; - - } - } -} diff --git a/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovConesSIMD.icpp b/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovConesSIMD.icpp deleted file mode 100644 index 339693b184..0000000000 --- a/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovConesSIMD.icpp +++ /dev/null @@ -1,257 +0,0 @@ - -{ - - // types - using ScFloat = float; - using VcFloat = Vc::float_v; - using VcInt = Vc::int_v; - using ScInt = int; - using VcPoint = LHCbROOT::Math::PositionVector3D < LHCbROOT::Math::Cartesian3D<VcFloat> >; - using VcVector = LHCbROOT::Math::DisplacementVector3D< LHCbROOT::Math::Cartesian3D<VcFloat> >; - using VcPlane = LHCbROOT::Math::Impl::Plane3D<VcFloat>; - - // Ray tracing utils - using namespace Rich::RayTracingUtils; - - // The data to return - MassHypoRingsVector ringsV; - ringsV.reserve( segments.size() ); - - // Temporary working photon object. Need to eventually remove need for this. - GeomPhoton photon; - - // local position corrector - // longer term need to remove this - const Rich::Rec::RadPositionCorrector corrector; - - // loop over the input data - for ( const auto && data : Ranges::ConstZip(segments,ckAngles) ) - { - const auto & segment = std::get<0>(data); - const auto & ckTheta = std::get<1>(data); - - // Add a set of mass hypo rings for this segment - ringsV.emplace_back( ); - auto & rings = ringsV.back(); - - // which rich and radiator - const auto rich = segment.rich(); - const auto rad = segment.radiator(); - - // best emission point - const auto & ePnt = segment.bestPoint(); - - // Start detector side - const auto side = m_rich[rich]->side(ePnt); - - // Number of VcVector objects - const auto NVC = m_nPoints[rad] / VcFloat::Size; - - // Loop over PID types - for ( const auto id : activeParticles() ) - { - // Above threshold ? - if ( ckTheta[id] > 0 ) - { - - // compute sin and cos theta - double sinTheta(0), cosTheta(0); - vdt::fast_sincos( ckTheta[id], sinTheta, cosTheta ); - - // reserve size in the points container - rings[id].reserve( m_nPoints[rad] ); - - // Form the starting detector sides - VcAllocVector<VcInt> photSides( NVC, VcInt(side) ); - - // Form the starting points - VcAllocVector<VcPoint> startPoints( NVC, VcPoint(ePnt.x(),ePnt.y(),ePnt.z()) ); - - // Form the starting points and directions. - VcAllocVector<VcVector> startDirs; - // Will be able to vectorise this better once GenVector in ROOT has my updates - { - unsigned int nPhot(0); - // Vc vectors for (x,y,z) - VcFloat x,y,z; - for ( auto iP = m_cosSinPhiV[rad].begin(); iP != m_cosSinPhiV[rad].end(); ++iP, ++nPhot ) - { - // Vc index - const auto ivc = nPhot % VcFloat::Size; - // Photon direction around loop - const auto photDir = - segment.vectorAtCosSinThetaPhi( cosTheta, sinTheta, - (*iP).cosPhi, (*iP).sinPhi ); - // Fill Vc words - x[ivc] = photDir.x(); - y[ivc] = photDir.y(); - z[ivc] = photDir.z(); - // If last index, make a new entry in the vector and fill - if ( VcFloat::Size-1 == ivc ) { startDirs.emplace_back(x,y,z); } - } - } - - // Starting CoC values - VcAllocVector<VcPoint> CoCs( NVC, VcPoint( m_rich[rich]->nominalCentreOfCurvature(side) ) ); - - // Starting RoC values - VcAllocVector<VcFloat> RoCs( NVC, VcFloat( m_rich[rich]->sphMirrorRadius() ) ); - - // Intersect with the spherical mirrors to find the reflection points and use these - // to find the mirror segments to use for the primary mirrors - for ( auto && data : Ranges::Zip(startPoints,startDirs,CoCs,RoCs,photSides) ) - { - auto & startP = std::get<0>(data); - auto & startD = std::get<1>(data); - auto & CoC = std::get<2>(data); - auto & RoC = std::get<3>(data); - auto & sides = std::get<4>(data); - - // interset with nominal primary - VcPoint nomSphInter; - auto mask = intersectSpherical( startP, startD, CoC, RoC, nomSphInter ); - if ( any_of(mask) ) - { - - // Check if we are on the same detector side or not - VcInt newSides(sides); - // To Do - Fix RichDet Vc support - //m_rich[rich]->sides( nomSphInter, newSides ); - { - VcFloat x(CoC.x()), y(CoC.y()), z(CoC.z()); - for ( std::size_t i = 0; i < VcFloat::Size; ++i ) - { - // Check the detector side for the intersection point - const auto nside = m_rich[rich]->side( (ScFloat)nomSphInter.x()[i], - (ScFloat)nomSphInter.y()[i] ); - newSides[i] = ScInt( nside ); - if ( newSides[i] != sides[i] ) - { - // Update CoC and RoC for this entry - const auto& nCoC = m_rich[rich]->nominalCentreOfCurvature(nside); - x[i] = nCoC.x(); - y[i] = nCoC.y(); - z[i] = nCoC.z(); - RoC[i] = m_rich[rich]->sphMirrorRadius(); - } - } - // Update the CoC point - CoC = VcPoint(x,y,z); - } - // if any think changed rerun the intersection - if ( UNLIKELY( any_of( sides != newSides ) ) ) - { - sides = newSides; - mask &= intersectSpherical( startP, startD, CoC, RoC, nomSphInter ); - } - - if ( any_of(mask) ) - { - - { - // Copy the CoC parameters - VcFloat x(CoC.x()), y(CoC.y()), z(CoC.z()); - // Find primary mirror segments to update CoC and RoC foreach photon - for ( std::size_t i = 0; i < VcFloat::Size; ++i ) - { - // Find the primary mirror segment for this point - const auto * sphSegment = - m_mirrorSegFinder.get()->findSphMirror( rich, side, - (ScFloat)nomSphInter.x()[i], - (ScFloat)nomSphInter.y()[i] ); - // update the mirror parameters - const auto& nCoC = sphSegment->centreOfCurvature(); - x[i] = nCoC.x(); - y[i] = nCoC.y(); - z[i] = nCoC.z(); - RoC[i] = sphSegment->radius(); - } - // Update the CoC point - CoC = VcPoint(x,y,z); - } - - // perform the final reflection on the primaries - mask &= reflectSpherical( startP, startD, CoC, RoC ); - - if ( any_of(mask) ) - { - // move on to the secondary mirrors - - // nominal intersection point - VcPoint planeInt; - const auto& plane = m_rich[rich]->nominalPlane(side); - VcPlane vcplane( plane.A(), plane.B(), plane.C(), plane.D() ); - mask &= intersectPlane( startP, startD, vcplane, planeInt ); - - if ( any_of(mask) ) - { - // Find the exact secondary mirror segments - - // Copy the nominal plane parameters - auto A(vcplane.A()), B(vcplane.B()), C(vcplane.C()), D(vcplane.D()); - // Copy the CoC parameters - VcFloat x(CoC.x()), y(CoC.y()), z(CoC.z()); - for ( std::size_t i = 0; i < VcFloat::Size; ++i ) - { - // find secondary mirror segment - const auto * secSegment = - m_mirrorSegFinder.get()->findSecMirror( rich, side, - (ScFloat)planeInt.x()[i], - (ScFloat)planeInt.y()[i] ); - // flat versus spherical treatment - if ( m_treatSecMirrsFlat[rich] ) - { - // Update the normal plane - const auto & npl = secSegment->centreNormalPlane(); - A[i] = npl.A(); - B[i] = npl.B(); - C[i] = npl.C(); - D[i] = npl.D(); - } - else - { - // update speherical parameters for the secondary mirrors - const auto& nCoC = secSegment->centreOfCurvature(); - x[i] = nCoC.x(); - y[i] = nCoC.y(); - z[i] = nCoC.z(); - RoC[i] = secSegment->radius(); - } - } - - // reflect off the secondary mirrors - mask &= ( m_treatSecMirrsFlat[rich] ? - reflectPlane ( startP, startD, VcPlane(A,B,C,D) ) : - reflectSpherical( startP, startD, VcPoint(x,y,z), RoC ) ); - - - // If OK, proceed to getting the hit position - if ( any_of(mask) ) - { - - - - - - - } - - } - - } - - } - - } // first intersection ok - - } // loop over photons - - - } - - } - - } - - return ringsV; -} diff --git a/Rich/RichFutureRecTrackAlgorithms/src/avx/RichRayTraceCherenkovCones.cpp b/Rich/RichFutureRecTrackAlgorithms/src/avx/RichRayTraceCherenkovCones.cpp deleted file mode 100644 index 067b58c58b..0000000000 --- a/Rich/RichFutureRecTrackAlgorithms/src/avx/RichRayTraceCherenkovCones.cpp +++ /dev/null @@ -1,14 +0,0 @@ - -// local -#include "../RichRayTraceCherenkovConesSIMD.h" - -// All code is in general Rich reconstruction namespace -using namespace Rich::Future::Rec; - -MassHypoRingsVector -RayTraceCherenkovConesSIMD:: -run_avx( const LHCb::RichTrackSegment::Vector& segments, - const CherenkovAngles::Vector& ckAngles ) const -{ -#include "../RichRayTraceCherenkovConesSIMD.icpp" -} diff --git a/Rich/RichFutureRecTrackAlgorithms/src/avx2/RichRayTraceCherenkovCones.cpp b/Rich/RichFutureRecTrackAlgorithms/src/avx2/RichRayTraceCherenkovCones.cpp deleted file mode 100644 index f7db884820..0000000000 --- a/Rich/RichFutureRecTrackAlgorithms/src/avx2/RichRayTraceCherenkovCones.cpp +++ /dev/null @@ -1,14 +0,0 @@ - -// local -#include "../RichRayTraceCherenkovConesSIMD.h" - -// All code is in general Rich reconstruction namespace -using namespace Rich::Future::Rec; - -MassHypoRingsVector -RayTraceCherenkovConesSIMD:: -run_avx2( const LHCb::RichTrackSegment::Vector& segments, - const CherenkovAngles::Vector& ckAngles ) const -{ -#include "../RichRayTraceCherenkovConesSIMD.icpp" -} diff --git a/Rich/RichFutureRecTrackAlgorithms/src/generic/RichRayTraceCherenkovCones.cpp b/Rich/RichFutureRecTrackAlgorithms/src/generic/RichRayTraceCherenkovCones.cpp deleted file mode 100644 index 311c28b8d8..0000000000 --- a/Rich/RichFutureRecTrackAlgorithms/src/generic/RichRayTraceCherenkovCones.cpp +++ /dev/null @@ -1,14 +0,0 @@ - -// local -#include "../RichRayTraceCherenkovConesSIMD.h" - -// All code is in general Rich reconstruction namespace -using namespace Rich::Future::Rec; - -MassHypoRingsVector -RayTraceCherenkovConesSIMD:: -run_generic( const LHCb::RichTrackSegment::Vector& segments, - const CherenkovAngles::Vector& ckAngles ) const -{ -#include "../RichRayTraceCherenkovConesSIMD.icpp" -} diff --git a/Rich/RichFutureRecTrackAlgorithms/src/sse4/RichRayTraceCherenkovCones.cpp b/Rich/RichFutureRecTrackAlgorithms/src/sse4/RichRayTraceCherenkovCones.cpp deleted file mode 100644 index 4b59308297..0000000000 --- a/Rich/RichFutureRecTrackAlgorithms/src/sse4/RichRayTraceCherenkovCones.cpp +++ /dev/null @@ -1,14 +0,0 @@ - -// local -#include "../RichRayTraceCherenkovConesSIMD.h" - -// All code is in general Rich reconstruction namespace -using namespace Rich::Future::Rec; - -MassHypoRingsVector -RayTraceCherenkovConesSIMD:: -run_sse4( const LHCb::RichTrackSegment::Vector& segments, - const CherenkovAngles::Vector& ckAngles ) const -{ -#include "../RichRayTraceCherenkovConesSIMD.icpp" -} -- GitLab From bf1637b6a1153a11b37b6c5807c26db3aaa0a98b Mon Sep 17 00:00:00 2001 From: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Sat, 4 Mar 2017 11:37:58 +0100 Subject: [PATCH 30/68] Remove test options --- .../python/RichFutureRecSys/ConfiguredRichReco.py | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/Rich/RichFutureRecSys/python/RichFutureRecSys/ConfiguredRichReco.py b/Rich/RichFutureRecSys/python/RichFutureRecSys/ConfiguredRichReco.py index 9fc833512e..c21660c283 100644 --- a/Rich/RichFutureRecSys/python/RichFutureRecSys/ConfiguredRichReco.py +++ b/Rich/RichFutureRecSys/python/RichFutureRecSys/ConfiguredRichReco.py @@ -322,7 +322,6 @@ def RichRecoSequence( GroupName = "", # Optional name given to this group. from Configurables import Rich__Future__Rec__TrackEmittedCherenkovAngles as EmittedCherenkovAngles from Configurables import Rich__Future__Rec__TrackSignalCherenkovAngles as SignalCherenkovAngles from Configurables import Rich__Future__Rec__RayTraceCherenkovCones as EmittedMassCones - from Configurables import Rich__Future__Rec__RayTraceCherenkovConesSIMD as EmittedMassConesSIMD from Configurables import Rich__Future__Rec__GeomEffCKMassRings as GeomEff from Configurables import Rich__Future__Rec__TrackFunctionalCherenkovResolutions as TrackCKResolutions from Configurables import Rich__Future__Rec__SelectTrackSegments as SelectTrackSegments @@ -387,16 +386,6 @@ def RichRecoSequence( GroupName = "", # Optional name given to this group. # Options emitMassCones.NRingPoints = NRingPoints - # Cherenkov mass cones using emitted spectra SIMD - emitMassConesSIMD = makeRichAlg( EmittedMassConesSIMD, "RichMassConesSIMD"+name, algprops ) - # Input - emitMassConesSIMD.TrackSegmentsLocation = locs["TrackSegmentsLocation"] - emitMassConesSIMD.CherenkovAnglesLocation = locs["EmittedCherenkovAnglesLocation"] - # Output - emitMassConesSIMD.MassHypothesisRingsLocation = locs["EmittedMassHypothesisRingsLocation"]+"SIMD" - # Options - emitMassConesSIMD.NRingPoints = NRingPoints - # Detectable photon yields detY = makeRichAlg( DetectableYields, "RichDetectableYields"+name, algprops ) # Inputs @@ -465,7 +454,7 @@ def RichRecoSequence( GroupName = "", # Optional name given to this group. segs = GaudiSequencer( "RichTracks" + name, MeasureTime = MeasureTime, Members = [ segCr, tkGloPnts, tkLocPnts, emitY, - emitChAngles, emitMassCones, emitMassConesSIMD, detY, + emitChAngles, emitMassCones, detY, geomEff, tkSel, sigYields, sigChAngles, tkRes ] ) # Add to final sequence tkSeq.Members += [ segs ] -- GitLab From 981435e0ac9d25e9109f58281204ee61931230af Mon Sep 17 00:00:00 2001 From: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Sat, 4 Mar 2017 11:38:34 +0100 Subject: [PATCH 31/68] Use vectorised ray tracing from RichRayTraceCherenkovCones --- .../CMakeLists.txt | 20 +-- .../src/RichRayTraceCherenkovCones.cpp | 114 +++++++++++++----- .../src/RichRayTraceCherenkovCones.h | 4 + 3 files changed, 92 insertions(+), 46 deletions(-) diff --git a/Rich/RichFutureRecTrackAlgorithms/CMakeLists.txt b/Rich/RichFutureRecTrackAlgorithms/CMakeLists.txt index 9873e24314..c4c1f41f28 100644 --- a/Rich/RichFutureRecTrackAlgorithms/CMakeLists.txt +++ b/Rich/RichFutureRecTrackAlgorithms/CMakeLists.txt @@ -8,28 +8,16 @@ gaudi_depends_on_subdirs(Rich/RichFutureRecBase Rich/RichUtils Rich/RichFutureUtils Tr/TrackKernel - Tr/TrackInterfaces - Kernel/TemplatedGenVector - Kernel/Vc - Kernel/VectorClass) + Tr/TrackInterfaces) find_package(ROOT) find_package(Boost) find_package(GSL) find_package(VDT) -find_package(Vc) include_directories(SYSTEM ${Boost_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS} ${Vc_INCLUDE_DIR}) gaudi_add_module(RichFutureRecTrackAlgorithms - src/*.cpp src/generic/*.cpp src/sse4/*.cpp src/avx/*.cpp src/avx2/*.cpp - INCLUDE_DIRS Vc Boost GSL VDT Kernel/VectorClass Rich/RichFutureRecBase Rich/RichUtils Rich/RichFutureUtils Tr/TrackInterfaces Tr/TrackKernel - LINK_LIBRARIES Boost GSL VDT RichFutureRecBase RichUtils RichFutureUtils TemplatedGenVectorLib ) - -target_link_libraries( RichFutureRecTrackAlgorithms "${Vc_LIB_DIR}/libVc.a" ) - -set_property(SOURCE src/RichRayTraceCherenkovConesSIMD.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-ignored-attributes " ) -set_property(SOURCE src/generic/RichRayTraceCherenkovCones.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-ignored-attributes " ) -set_property(SOURCE src/sse4/RichRayTraceCherenkovCones.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-ignored-attributes -O3 -msse4.2 " ) -set_property(SOURCE src/avx/RichRayTraceCherenkovCones.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-ignored-attributes -O3 -mavx -fabi-version=0 -fabi-compat-version=0 -ffp-contract=fast " ) -set_property(SOURCE src/avx2/RichRayTraceCherenkovCones.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-ignored-attributes -O3 -mavx2 -mfma -fabi-version=0 -fabi-compat-version=0 -ffp-contract=fast " ) + src/*.cpp + INCLUDE_DIRS Boost GSL VDT Rich/RichFutureRecBase Rich/RichUtils Rich/RichFutureUtils Tr/TrackInterfaces Tr/TrackKernel + LINK_LIBRARIES Boost GSL VDT RichFutureRecBase RichUtils RichFutureUtils ) diff --git a/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovCones.cpp b/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovCones.cpp index b39a6afa73..f411bee2bd 100644 --- a/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovCones.cpp +++ b/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovCones.cpp @@ -110,46 +110,100 @@ RayTraceCherenkovCones::operator()( const LHCb::RichTrackSegment::Vector& segmen // reserve size in the points container rings[id].reserve( m_nPoints[rad] ); - // loop around the ring - unsigned int nOK(0), nPhot(0); - for ( auto iP = m_cosSinPhiV[rad].begin(); iP != m_cosSinPhiV[rad].end(); ++iP, ++nPhot ) + // Container for photon directions + std::vector<Gaudi::XYZVector> vects; + vects.reserve( m_nPoints[rad] ); + + // loop around the ring to create the directions + for ( const auto& P : m_cosSinPhiV[rad] ) { // Photon direction around loop - const auto photDir = - segment.vectorAtCosSinThetaPhi( cosTheta, sinTheta, - (*iP).cosPhi, (*iP).sinPhi ); - - // do the ray tracing - // really need to speed this up by removing virtual function call and need for photon. - const auto result = - m_rayTrace.get()->traceToDetector( rich, emissionPoint, photDir, photon, + vects.emplace_back( segment.vectorAtCosSinThetaPhi( cosTheta, sinTheta, + P.cosPhi, P.sinPhi ) ); + } + + // Which ray tracing to run + if ( m_useVectorised ) + { + + // The vectorised ray tracing + const auto results = + m_rayTrace.get()->traceToDetector( emissionPoint, vects, segment, m_traceModeRad[rad] ); + + // loop over the results and fill + unsigned int nOK(0), nPhot(0); + for ( const auto && data : Ranges::ConstZip(results,m_cosSinPhiV[rad]) ) + { + const auto & res = std::get<0>(data); + const auto & cosphi = std::get<1>(data); + + // count photons + ++nPhot; + + // Add a new point + const auto & gP = res.detectionPoint; + rings[id].emplace_back ( gP, + corrector.correct(m_idTool.get()->globalToPDPanel(gP),rad), + res.smartID, + (RayTracedCKRingPoint::Acceptance)(res.result), + res.primaryMirror, + res.secondaryMirror, + cosphi.phi ); + + // count raytraces that are in HPD panel + if ( res.result >= LHCb::RichTraceMode::InHPDPanel ) { ++nOK; } + + } + + } + else + { + + // Loop over the directions and ray trace them using the scalar method + unsigned int nOK(0), nPhot(0); + for ( const auto && data : Ranges::ConstZip(vects,m_cosSinPhiV[rad]) ) + { + const auto & photDir = std::get<0>(data); + const auto & cosphi = std::get<1>(data); + + // count photons + ++nPhot; + + // do the ray tracing + // really need to speed this up by removing virtual function call and need for photon. + const auto result = + m_rayTrace.get()->traceToDetector( rich, emissionPoint, photDir, photon, segment, m_traceModeRad[rad], Rich::top ); // Note forced side is not used.. - // Add a new point - const auto & gP = photon.detectionPoint(); - rings[id].emplace_back ( gP, - corrector.correct(m_idTool.get()->globalToPDPanel(gP),rad), - photon.smartID(), - (RayTracedCKRingPoint::Acceptance)(result), - photon.primaryMirror(), - photon.secondaryMirror(), - (*iP).phi ); - - // count raytraces that are in HPD panel - if ( result >= LHCb::RichTraceMode::InHPDPanel ) { ++nOK; } - - // bailout check - if ( 0 == nOK && nPhot >= m_nBailout[rad] ) break; + // Add a new point + const auto & gP = photon.detectionPoint(); + rings[id].emplace_back ( gP, + corrector.correct(m_idTool.get()->globalToPDPanel(gP),rad), + photon.smartID(), + (RayTracedCKRingPoint::Acceptance)(result), + photon.primaryMirror(), + photon.secondaryMirror(), + cosphi.phi ); + + // count raytraces that are in HPD panel + if ( result >= LHCb::RichTraceMode::InHPDPanel ) { ++nOK; } + + // bailout check + if ( 0 == nOK && nPhot >= m_nBailout[rad] ) break; + } + + // if no good hits empty the container + if ( 0 == nOK ) { rings[id].clear(); } } - + } - + } - + } - + return ringsV; } diff --git a/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovCones.h b/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovCones.h index cb61557178..9b653e9356 100644 --- a/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovCones.h +++ b/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovCones.h @@ -122,6 +122,10 @@ namespace Rich Gaudi::Property< RadiatorArray<float> > m_bailoutFrac { this, "BailoutFraction", { 0.75, 0.75, 0.75 } }; + /// Use the scalar or vector ray tracing + Gaudi::Property<bool> m_useVectorised + { this, "UseVectorisedRayTracing", true }; + /// Ray tracing tool ToolHandle<const IRayTracing> m_rayTrace { "Rich::Future::RayTracing/RayTracing", this }; -- GitLab From 32cf0707fd7606f8dc31c59dbb07007545f51128 Mon Sep 17 00:00:00 2001 From: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Sat, 4 Mar 2017 16:13:21 +0100 Subject: [PATCH 32/68] Add new QuarticSollver from Rainer and Christina that uses a Newton Rhapson approach that is much faster than the original --- .../src/RichQuarticPhotonReco.h | 6 +- .../src/application/PhotonReco/main.cpp | 4 +- .../RichPhotonRecoUsingQuarticSoln.h | 4 +- .../RichRecUtils/RichRecUtils/QuarticSolver.h | 5 +- .../RichRecUtils/QuarticSolverNewton.h | 344 ++++++++++++++++++ 5 files changed, 352 insertions(+), 11 deletions(-) create mode 100755 Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h diff --git a/Rich/RichFutureRecPhotonAlgorithms/src/RichQuarticPhotonReco.h b/Rich/RichFutureRecPhotonAlgorithms/src/RichQuarticPhotonReco.h index 7f5d5fe2a0..8449cc5409 100644 --- a/Rich/RichFutureRecPhotonAlgorithms/src/RichQuarticPhotonReco.h +++ b/Rich/RichFutureRecPhotonAlgorithms/src/RichQuarticPhotonReco.h @@ -36,7 +36,7 @@ #include "RichDet/DeRichSphMirror.h" // Quartic Solver -#include "RichRecUtils/QuarticSolver.h" +#include "RichRecUtils/QuarticSolverNewton.h" // interfaces #include "RichInterfaces/IRichMirrorSegFinderLookUpTable.h" @@ -136,8 +136,8 @@ namespace Rich private: - /// Quartic Solver - Rich::Rec::QuarticSolver m_quarticSolver; + /// Newton Quartic Solver + Rich::Rec::QuarticSolverNewton m_quarticSolver; /// Rich1 and Rich2 detector elements DetectorArray<const DeRich *> m_rich = {{}}; diff --git a/Rich/RichRecPhotonTools/src/application/PhotonReco/main.cpp b/Rich/RichRecPhotonTools/src/application/PhotonReco/main.cpp index 20a2eb747d..462946f929 100644 --- a/Rich/RichRecPhotonTools/src/application/PhotonReco/main.cpp +++ b/Rich/RichRecPhotonTools/src/application/PhotonReco/main.cpp @@ -1,6 +1,6 @@ // Quartic Solver -#include "RichRecUtils/QuarticSolver.h" +#include "RichRecUtils/QuarticSolverNewton.h" // STL #include <random> @@ -10,7 +10,7 @@ #include <typeinfo> // Make an instance of the quartic solver -Rich::Rec::QuarticSolver qSolver; +Rich::Rec::QuarticSolverNewton qSolver; Gaudi::XYZPoint sphReflPoint; diff --git a/Rich/RichRecPhotonTools/src/component/RichPhotonRecoUsingQuarticSoln.h b/Rich/RichRecPhotonTools/src/component/RichPhotonRecoUsingQuarticSoln.h index b1618bab6d..6331185cce 100755 --- a/Rich/RichRecPhotonTools/src/component/RichPhotonRecoUsingQuarticSoln.h +++ b/Rich/RichRecPhotonTools/src/component/RichPhotonRecoUsingQuarticSoln.h @@ -56,7 +56,7 @@ #include "gsl/gsl_poly.h" // Quartic Solver -#include "RichRecUtils/QuarticSolver.h" +#include "RichRecUtils/QuarticSolverNewton.h" namespace Rich { @@ -175,7 +175,7 @@ namespace Rich mutable const ISnellsLawRefraction * m_snellsLaw = nullptr; /// Quartic Solver - QuarticSolver m_quarticSolver; + QuarticSolverNewton m_quarticSolver; /** @brief Flag to indicate if the unambiguous photon test should be performed * for each radiator diff --git a/Rich/RichRecUtils/RichRecUtils/QuarticSolver.h b/Rich/RichRecUtils/RichRecUtils/QuarticSolver.h index 4fbabe905e..115dd3f353 100755 --- a/Rich/RichRecUtils/RichRecUtils/QuarticSolver.h +++ b/Rich/RichRecUtils/RichRecUtils/QuarticSolver.h @@ -7,8 +7,7 @@ */ //---------------------------------------------------------------------- -#ifndef RICHRECPHOTONTOOLS_QuarticSolver_H -#define RICHRECPHOTONTOOLS_QuarticSolver_H 1 +#pragma once // Gaudi #include "GaudiKernel/Kernel.h" @@ -241,5 +240,3 @@ namespace Rich } } - -#endif // RICHRECPHOTONTOOLS_QuarticSolver_H diff --git a/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h b/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h new file mode 100755 index 0000000000..147cbde568 --- /dev/null +++ b/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h @@ -0,0 +1,344 @@ + +//---------------------------------------------------------------------- +/** @file QuarticSolverNewton.h + * + * @author Christina Quast, Rainer Schwemmer + * @date 2017-02-03 + */ +//---------------------------------------------------------------------- + +#pragma once + +// Gaudi +#include "GaudiKernel/Kernel.h" +#include "GaudiKernel/Transform3DTypes.h" +#include "GaudiKernel/Point3DTypes.h" +#include "GaudiKernel/Vector3DTypes.h" + +// VectorClass +#include "VectorClass/vectorclass.h" +#include "VectorClass/complexvec.h" + +// STL +#include <math.h> +#include <type_traits> + +// Eigen +#include "LHCbMath/EigenTypes.h" +#include <Eigen/Geometry> + +// VDT +#include "vdt/asin.h" + +// LHCb Maths +#include "LHCbMath/FastRoots.h" + +namespace Rich +{ + namespace Rec + { + + //----------------------------------------------------------------------------- + /** @class QuarticSolverNewton + * + * Utility class that implements the solving of the Quartic equation for the RICH + * Based on original code by Chris Jones + * + * @author Christina Quast, Rainer Schwemmer + * @date 2017-02-03 + */ + //----------------------------------------------------------------------------- + class QuarticSolverNewton + { + + public: + + // Use eigen types + typedef LHCb::Math::Eigen::XYZPoint Point; ///< Point type + typedef LHCb::Math::Eigen::XYZVector Vector; ///< vector type + + public: + + /** Solves the characteristic quartic equation for the RICH optical system. + * + * See note LHCB/98-040 RICH section 3 for more details + * + * @param emissionPoint Assumed photon emission point on track + * @param CoC Spherical mirror centre of curvature + * @param virtDetPoint Virtual detection point + * @param radius Spherical mirror radius of curvature + * @param sphReflPoint The reconstructed reflection pont on the spherical mirror + * + * @return boolean indicating status of the quartic solution + * @retval true Calculation was successful. sphReflPoint is valid. + * @retval false Calculation failed. sphReflPoint is not valid. + */ + template< class TYPE > + inline void solve( const Gaudi::XYZPoint& emissionPoint, + const Gaudi::XYZPoint& CoC, + const Gaudi::XYZPoint& virtDetPoint, + const TYPE radius, + Gaudi::XYZPoint& sphReflPoint ) const + { + + // typedefs vectorised types + typedef Eigen::Matrix< TYPE , 3 , 1 > Eigen3Vector; + using Vec4x = typename std::conditional<std::is_same<TYPE,float>::value,Vec4f,Vec4d>::type; + + // vector from mirror centre of curvature to assumed emission point + const Vector evec( emissionPoint - CoC ); + const TYPE e2 = evec.dot(evec); + + // vector from mirror centre of curvature to virtual detection point + const Vector dvec( virtDetPoint - CoC ); + const TYPE d2 = dvec.dot(dvec); + + // various quantities needed to create quartic equation + // see LHCB/98-040 section 3, equation 3 + const TYPE ed2 = e2 * d2; + //std::pow uses internal loop and causes branch misses and other inefficiencies + //There might be a constant exponent pow function too, but i'm too lazy to check. + const TYPE cosgamma2 = ( ed2 > 0 ? std::pow(evec.dot(dvec),2)/ed2 : 1.0 ); + //const TYPE cosgamma2 = ( ed2 > 0.0f ? evec.dot(dvec)*evec.dot(dvec)/ed2 : 1.0f ); + // vectorise 4 square roots into 1 + //TODO: This vectorized sqrt is questionable. There is a lot of overhead in gathering + //The different components via unaligned loads. It's probably not + //Faster than just computing the 4 square roots individually. + const auto tmp_sqrt = sqrt( Vec4x( e2, d2, + cosgamma2 < 1.0f ? 1.0f-cosgamma2 : 0.0f, + cosgamma2 ) ); + const TYPE e = tmp_sqrt[0]; + const TYPE d = tmp_sqrt[1]; + const TYPE singamma = tmp_sqrt[2]; + const TYPE cosgamma = tmp_sqrt[3]; + + const TYPE dx = d * cosgamma; + const TYPE dy = d * singamma; + const TYPE r2 = radius * radius; + const TYPE dy2 = dy * dy; + const TYPE edx = e + dx; + + // Fill array for quartic equation + const auto a0 = 4.0f * ed2; + //Newton solver doesn't care about a0 being not 1.0. Remove costly division and several multiplies. + //This has some downsides though. The a-values are hovering around a numerical value of 10^15. single + //precision float max is 10^37. A single square and some multiplies will push it over the limit of what + //single precision float can handle. It's ok for the newton method, but Halley or higher order Housholder + //will fail without this normalization. + //const auto inv_a0 = ( a0 > 0 ? 1.0 / a0 : std::numeric_limits<TYPE>::max() ); + const TYPE dyrad2 = 2.0f * dy * radius; + const TYPE a1 = - ( 2.0f * dyrad2 * e2 );// * inv_a0; + const TYPE a2 = ( (dy2 * r2) + ( edx * edx * r2 ) - a0 );// * inv_a0; + const TYPE a3 = ( dyrad2 * e * (e-dx) );// * inv_a0; + const TYPE a4 = ( ( e2 - r2 ) * dy2 );// * inv_a0; + + // use simplified RICH version of quartic solver + // const auto sinbeta = solve_quartic_RICH<TYPE>( a1, // a + // a2, // b + // a3, // c + // a4 // d + // ); + + //Use optimized newton solver on quartic equation. + const auto sinbeta = solve_quartic_newton_RICH( a0, a1, a2, a3, a4 ); + + //TODO: This method should be better but has problems still for some reasons + //const auto sinbeta = solve_quartic_housholder_RICH<TYPE, 3>(a1, a2, a3, a4); + + // construct rotation transformation + // Set vector magnitude to radius + // rotate vector and update reflection point + //rotation matrix uses sin(beta) and cos(beta) to perform rotation + //even fast_asinf (which is only single precision and defeats the purpose + //of this class being templatable to double btw) is still too slow + //plus there is a cos and sin call inside AngleAxis ... + //We can do much better by just using the cos(beta) we already have to calculate + //sin(beta) and do our own rotation. On top of that we rotate non-normalized and save several + //Divisions by normalizing only once at the very end + //Again, care has to be taken since we are close to float_max here without immediate normalization. + //As far as we have tried with extreme values in the rich coordinate systems this is fine. + //const Eigen::AngleAxis<TYPE> angleaxis( vdt::fast_asinf(sinbeta), + // Eigen3Vector(n[0],n[1],n[2]) ); + const TYPE nx = (evec[1]*dvec[2]) - (evec[2]*dvec[1]); + const TYPE ny = (evec[2]*dvec[0]) - (evec[0]*dvec[2]); + const TYPE nz = (evec[0]*dvec[1]) - (evec[1]*dvec[0]); + //const auto n = evec.cross3(dvec); + //const auto norm = n.dot(n); + const TYPE norm = nx*nx + ny*ny + nz*nz; + const TYPE norm_sqrt = std::sqrt(norm); + + const TYPE a = sinbeta * norm_sqrt; + const TYPE b = ( TYPE(1.0) - std::sqrt( TYPE(1.0) - (sinbeta*sinbeta) ) ); // <--(1-cos(beta)) + const TYPE enorm = radius/(e*norm); + + //Perform non-normalized rotation + const std::array<TYPE,9> M = + { norm + b*(-nz*nz-ny*ny), a*nz+b*nx*ny, -a*ny+b*nx*nz, + -a*nz+b*nx*ny, norm+b*(-nx*nx-nz*nz), a*nx+b*ny*nz, + a*ny+b*nx*nz, -a*nx+b*ny*nz, norm+b*(-ny*ny-nx*nx) }; + + //re-normalize rotation and scale to radius in one step + const TYPE ex = enorm*(evec[0]*M[0]+evec[1]*M[3]+evec[2]*M[6]); + const TYPE ey = enorm*(evec[0]*M[1]+evec[1]*M[4]+evec[2]*M[7]); + const TYPE ez = enorm*(evec[0]*M[2]+evec[1]*M[5]+evec[2]*M[8]); + + sphReflPoint = ( CoC + Gaudi::XYZVector( ex, ey, ez ) ); + } + + private: + + //A newton iteration solver for the Rich quartic equation + //Since the polynomial that is evaluated here is extremely constrained + //(root is in small interval, one root guaranteed), we can use a much more + //efficient approximation (which still has the same precision) instead of the + //full blown mathematically absolute correct method and still end up with + //usable results + + template < class TYPE > + inline TYPE f4(const TYPE &a0, const TYPE &a1, const TYPE &a2, const TYPE &a3, const TYPE &a4, TYPE &x) const + { + //return (a0 * x*x*x*x + a1 * x*x*x + a2 * x*x + a3 * x + a4); + //A bit more FMA friendly + return ((((a0*x)+a1)*x+a2)*x+a3)*x+a4; + } + + template < class TYPE > + inline TYPE df4(const TYPE &a0, const TYPE &a1, const TYPE &a2, const TYPE &a3, TYPE &x) const + { + //return (4.0f*a0 * x*x*x + 3.0f*a1 * x*x + 2.0f*a2 * x + a3); + return (((4.0f * a0*x)+3.0f*a1)*x+2.0f*a2)*x+a3; + } + + /** Horner's method to evaluate the polynomial and its derivatives with as little math operations as + * possible. We use a template here to allow the compiler to unroll the for loops and produce code + * that is free from branches and optimized for the grade of polynomial and derivatives as necessary. + */ + template < class TYPE, std::size_t ORDER = 4, std::size_t DIFFGRADE = 3 > + inline void evalPolyHorner(const TYPE (&a)[ORDER+1], TYPE (&res)[DIFFGRADE+1], TYPE x) const + { + for(unsigned int i = 0; i <= DIFFGRADE; i++) + { + res[i] = a[0]; + } + + for(unsigned int j = 1; j <= ORDER; j++) + { + res[0] = res[0] * x + a[j]; + int l = (ORDER - j) > DIFFGRADE ? DIFFGRADE : ORDER - j; + for (int i = 1; i <= l ; i++) + { + res[i] = res[i] * x + res[i-1]; + } + } + + //TODO: Check assembly to see if this is optimized away if DIFFGRADE is <= 2 + float l = 1.0; + for(unsigned int i = 2; i <= DIFFGRADE; i++) + { + l *= i; + res[i] = res[i] * l; + } + + } + + /** 3rd grade Housholder's method for iteratively finding the root of a function. Tests have shown that we seem to be + * already too constrained in our polynomial and input data that we are not gaining anything over newton. In fact it seems + * to make performance worse. + * TODO: find out why performance of this is so bad. We might be missing something. It should converge much faster than newton. + */ + template < class TYPE, std::size_t ITER = 3 > + inline TYPE householder(const TYPE (&a)[5], TYPE x0) const + { + TYPE res[4]; + for(unsigned int i = 0; i < ITER; i++) + { + evalPolyHorner<TYPE, 4, 3>(a, res, x0); + x0 = x0 - ((6.0 * res[0]*res[1]*res[1] - 3.0 * res[0]*res[0]*res[2])/ + (6.0 * res[1]*res[1]*res[1] - 6.0 * res[0]*res[1]*res[2] + res[0]*res[0]*res[3])); + //std::cout << x0 << ": " << res[0] << ", " << res[1] << ", " << res[2] << ", "<< res[3] << ", " << std::endl; + + } + return x0; + } + + /** Use Housholder's method to solve the rich quartic equation. Important! If this function is used, the coefficients of the + * polynomial have to be normalized. They are typically around 10^15 and floating point overflows will occur in here if these + * large values are used. + */ + template < class TYPE , std::size_t ITER = 3 > + inline TYPE solve_quartic_housholder_RICH( const TYPE& a0, + const TYPE& a1, + const TYPE& a2, + const TYPE& a3) const + { + //Starting value for housholder iteration. Empirically values seem to be + //between 0 0and 0.4 so we chose the value in the middle as starting point + TYPE x0 = 0.2f; + + TYPE a[5] = {1.0f, a0, a1, a2, a3}; + //std::cout << "Polynomial: " << std::endl; + //std::cout << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ", " << a[4] << std::endl; + x0 = householder<TYPE, ITER>(a, x0); + + return x0; + } + + /** Newton-Rhapson method for calculating the root of the rich polynomial. It uses the bisection method in the beginning + * to get close enough to the root to allow the second stage newton method to converge faster. After 4 iterations of newton + * precision is as good as single precision floating point will get you. We have introduced a few tuning parameters like the + * newton gain factor and a slightly skewed bisection division, which in this particular case help to speed things up. + * TODO: Once we are happy with the number of newton and bisection iterations, this function should be templated to the number of + * these iterations to allow loop unrolling and elimination of unnecessary branching + * TODO: These tuning parameters have been found by low effort experimentation on random input data. A more detailed + * study should be done with real data to find the best values + */ + template < class TYPE > + inline TYPE solve_quartic_newton_RICH( const TYPE& a0, + const TYPE& a1, + const TYPE& a2, + const TYPE& a3, + const TYPE& a4 ) const + { + TYPE epsilon; + //Use N steps of bisection method to find starting point for newton + TYPE l(0); + TYPE u(0.5); + TYPE m(0.2); //We start a bit off center since the distribution of roots tends to be more to the left side + const TYPE a[5] = {a0, a1, a2, a3, a4}; + TYPE res[2]; + for ( int i = 0; i < 3; ++i ) + { + auto oppositeSign = std::signbit(f4(a0,a1,a2,a3,a4,m) * f4(a0,a1,a2,a3,a4,l)); + + l = oppositeSign ? l : m; + u = oppositeSign ? m : u; + //std::cout << l.extract(0) << ", " << m.extract(0) << ", " << u.extract(0) << ", " << oppositeSign.extract(0) << std::endl; + //0.4 instead of 0.5 to speed up convergence. Most roots seem to be closer to 0 than to the extreme end + m = (u + l) * 0.4; + } + + //Newton for the rest + TYPE x = m; + + //Most of the times we are approaching the root of the polynomial from one side + //and fall short by a certain fraction. This fraction seems to be around 1.04 of the + //quotient which is subtracted from x. By scaling it up, we take bigger steps towards + //the root and thus converge faster. + //TODO: study this factor more closely it's pure guesswork right now. We might get + //away with 3 iterations if we can find an exact value + const TYPE gain = 1.04; + + for ( int i = 0; i < 4; ++i ) + { + evalPolyHorner<TYPE, 4, 1>(a, res, x); + //epsilon = f4(a0,a1,a2,a3,a4,x) / df4(a0,a1,a2,a3,x); + epsilon = res[0] / res[1]; + x = x - gain * epsilon; + } + return x; + } + + }; + + } +} -- GitLab From e4fafc8f92afd5c01a2f76d4eec3f8c7ed65ff32 Mon Sep 17 00:00:00 2001 From: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Sat, 4 Mar 2017 16:32:24 +0100 Subject: [PATCH 33/68] template the number if NR iterations --- .../RichRecUtils/QuarticSolverNewton.h | 33 ++++++++++--------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h b/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h index 147cbde568..c85a472525 100755 --- a/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h +++ b/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h @@ -216,16 +216,16 @@ namespace Rich template < class TYPE, std::size_t ORDER = 4, std::size_t DIFFGRADE = 3 > inline void evalPolyHorner(const TYPE (&a)[ORDER+1], TYPE (&res)[DIFFGRADE+1], TYPE x) const { - for(unsigned int i = 0; i <= DIFFGRADE; i++) + for ( unsigned int i = 0; i <= DIFFGRADE; ++i ) { res[i] = a[0]; } - for(unsigned int j = 1; j <= ORDER; j++) + for ( unsigned int j = 1; j <= ORDER; ++j ) { res[0] = res[0] * x + a[j]; int l = (ORDER - j) > DIFFGRADE ? DIFFGRADE : ORDER - j; - for (int i = 1; i <= l ; i++) + for ( int i = 1; i <= l ; ++i ) { res[i] = res[i] * x + res[i-1]; } @@ -233,7 +233,7 @@ namespace Rich //TODO: Check assembly to see if this is optimized away if DIFFGRADE is <= 2 float l = 1.0; - for(unsigned int i = 2; i <= DIFFGRADE; i++) + for ( unsigned int i = 2; i <= DIFFGRADE; ++i ) { l *= i; res[i] = res[i] * l; @@ -250,11 +250,11 @@ namespace Rich inline TYPE householder(const TYPE (&a)[5], TYPE x0) const { TYPE res[4]; - for(unsigned int i = 0; i < ITER; i++) + for ( unsigned int i = 0; i < ITER; ++i ) { evalPolyHorner<TYPE, 4, 3>(a, res, x0); - x0 = x0 - ((6.0 * res[0]*res[1]*res[1] - 3.0 * res[0]*res[0]*res[2])/ - (6.0 * res[1]*res[1]*res[1] - 6.0 * res[0]*res[1]*res[2] + res[0]*res[0]*res[3])); + x0 -= ((6.0 * res[0]*res[1]*res[1] - 3.0 * res[0]*res[0]*res[2])/ + (6.0 * res[1]*res[1]*res[1] - 6.0 * res[0]*res[1]*res[2] + res[0]*res[0]*res[3])); //std::cout << x0 << ": " << res[0] << ", " << res[1] << ", " << res[2] << ", "<< res[3] << ", " << std::endl; } @@ -292,21 +292,20 @@ namespace Rich * TODO: These tuning parameters have been found by low effort experimentation on random input data. A more detailed * study should be done with real data to find the best values */ - template < class TYPE > + template < class TYPE, std::size_t BISECTITS = 2, std::size_t NEWTONITS = 3 > inline TYPE solve_quartic_newton_RICH( const TYPE& a0, const TYPE& a1, const TYPE& a2, const TYPE& a3, const TYPE& a4 ) const { - TYPE epsilon; //Use N steps of bisection method to find starting point for newton TYPE l(0); TYPE u(0.5); TYPE m(0.2); //We start a bit off center since the distribution of roots tends to be more to the left side const TYPE a[5] = {a0, a1, a2, a3, a4}; TYPE res[2]; - for ( int i = 0; i < 3; ++i ) + for ( std::size_t i = 0; i <= BISECTITS; ++i ) { auto oppositeSign = std::signbit(f4(a0,a1,a2,a3,a4,m) * f4(a0,a1,a2,a3,a4,l)); @@ -318,7 +317,8 @@ namespace Rich } //Newton for the rest - TYPE x = m; + // CRJ : why copy the value. original value is not needed later on... + //TYPE x = m; //Most of the times we are approaching the root of the polynomial from one side //and fall short by a certain fraction. This fraction seems to be around 1.04 of the @@ -328,14 +328,15 @@ namespace Rich //away with 3 iterations if we can find an exact value const TYPE gain = 1.04; - for ( int i = 0; i < 4; ++i ) + for ( std::size_t i = 0; i <= NEWTONITS; ++i ) { - evalPolyHorner<TYPE, 4, 1>(a, res, x); + evalPolyHorner<TYPE, 4, 1>(a, res, m); //epsilon = f4(a0,a1,a2,a3,a4,x) / df4(a0,a1,a2,a3,x); - epsilon = res[0] / res[1]; - x = x - gain * epsilon; + TYPE epsilon = res[0] / res[1]; + m -= gain * epsilon; } - return x; + + return m; } }; -- GitLab From 3c472c72682aef78259dfb8f2fd1a38985bbea81 Mon Sep 17 00:00:00 2001 From: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Sat, 4 Mar 2017 16:48:19 +0100 Subject: [PATCH 34/68] Add templation of # iterations to public method --- Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h b/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h index c85a472525..016d24b96c 100755 --- a/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h +++ b/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h @@ -17,7 +17,6 @@ // VectorClass #include "VectorClass/vectorclass.h" -#include "VectorClass/complexvec.h" // STL #include <math.h> @@ -73,7 +72,7 @@ namespace Rich * @retval true Calculation was successful. sphReflPoint is valid. * @retval false Calculation failed. sphReflPoint is not valid. */ - template< class TYPE > + template< class TYPE, std::size_t BISECTITS = 2, std::size_t NEWTONITS = 3 > inline void solve( const Gaudi::XYZPoint& emissionPoint, const Gaudi::XYZPoint& CoC, const Gaudi::XYZPoint& virtDetPoint, -- GitLab From 569e569adeee6ddb965cbfad9112dce181b67a3c Mon Sep 17 00:00:00 2001 From: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Sat, 4 Mar 2017 16:50:11 +0100 Subject: [PATCH 35/68] resolve conflicts --- Rec/GlobalReco/root/RichKaonIDCompareFiles.C | 6 +++--- Rich/RichFutureRecSys/examples/Brunel.py | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Rec/GlobalReco/root/RichKaonIDCompareFiles.C b/Rec/GlobalReco/root/RichKaonIDCompareFiles.C index 0d62054025..abd6ca3a8a 100755 --- a/Rec/GlobalReco/root/RichKaonIDCompareFiles.C +++ b/Rec/GlobalReco/root/RichKaonIDCompareFiles.C @@ -51,14 +51,14 @@ void RichKaonIDCompareFiles() //const std::string dir = "/Users/chris/LHCb/RootFiles/Run2"; //const std::string dir = "/usera/jonesc/LHCbCMake/lhcb-head/BrunelDevNightly/output/Run2"; - const std::string dir = "/usera/jonesc/LHCbCMake/Brunel/output/future"; + const std::string dir = "/home/chris/LHCb/future"; typedef std::vector< std::tuple<std::string,std::string,Color_t> > PlotData; const PlotData plotdata = { - std::make_tuple ( "rich", "RICH Current", kBlack ), - std::make_tuple ( "richfuture", "RICH Future", kRed-6 ) + std::make_tuple ( "old-quartic", "Old Quartic", kBlack ), + std::make_tuple ( "new-quartic", "New NR Quartic", kRed-6 ) }; // const PlotData plotdata = diff --git a/Rich/RichFutureRecSys/examples/Brunel.py b/Rich/RichFutureRecSys/examples/Brunel.py index afccb289d4..c6b69a4c32 100644 --- a/Rich/RichFutureRecSys/examples/Brunel.py +++ b/Rich/RichFutureRecSys/examples/Brunel.py @@ -50,10 +50,10 @@ Brunel().MCCheckSequence = richs+["PROTO"] Brunel().OutputType = 'None' importOptions("$APPCONFIGOPTS/Persistency/Compression-ZLIB-1.py") -Brunel().EvtMax = 500 -Brunel().PrintFreq = 100 +Brunel().EvtMax = 10000 +Brunel().PrintFreq = 500 -#Brunel().Histograms = "Expert" +Brunel().Histograms = "Expert" #ApplicationMgr().ExtSvc += [ "AuditorSvc" ] -- GitLab From b67808d806d0e840de4209f10f1f3c4c0a7add93 Mon Sep 17 00:00:00 2001 From: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Sat, 4 Mar 2017 16:57:59 +0100 Subject: [PATCH 36/68] Adapt to changes in Eigen classes --- Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h b/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h index 016d24b96c..de00b7747c 100755 --- a/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h +++ b/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h @@ -50,12 +50,6 @@ namespace Rich class QuarticSolverNewton { - public: - - // Use eigen types - typedef LHCb::Math::Eigen::XYZPoint Point; ///< Point type - typedef LHCb::Math::Eigen::XYZVector Vector; ///< vector type - public: /** Solves the characteristic quartic equation for the RICH optical system. @@ -81,8 +75,10 @@ namespace Rich { // typedefs vectorised types - typedef Eigen::Matrix< TYPE , 3 , 1 > Eigen3Vector; + using Eigen3Vector = Eigen::Matrix< TYPE , 3 , 1 >; using Vec4x = typename std::conditional<std::is_same<TYPE,float>::value,Vec4f,Vec4d>::type; + using Vector = LHCb::Math::Eigen::XYZVector<TYPE>; + using Point = LHCb::Math::Eigen::XYZPoint<TYPE>; // vector from mirror centre of curvature to assumed emission point const Vector evec( emissionPoint - CoC ); -- GitLab From a5ffb96d761109c325d4bd87eb5b5900b62f0585 Mon Sep 17 00:00:00 2001 From: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Sat, 4 Mar 2017 18:06:10 +0100 Subject: [PATCH 37/68] Remove use of Eigen from QuarticSolverNewton.h --- .../RichRecUtils/QuarticSolverNewton.h | 79 +++++++++---------- 1 file changed, 37 insertions(+), 42 deletions(-) diff --git a/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h b/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h index de00b7747c..689c3d3c34 100755 --- a/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h +++ b/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h @@ -22,16 +22,9 @@ #include <math.h> #include <type_traits> -// Eigen -#include "LHCbMath/EigenTypes.h" -#include <Eigen/Geometry> - // VDT #include "vdt/asin.h" -// LHCb Maths -#include "LHCbMath/FastRoots.h" - namespace Rich { namespace Rec @@ -66,46 +59,46 @@ namespace Rich * @retval true Calculation was successful. sphReflPoint is valid. * @retval false Calculation failed. sphReflPoint is not valid. */ - template< class TYPE, std::size_t BISECTITS = 2, std::size_t NEWTONITS = 3 > - inline void solve( const Gaudi::XYZPoint& emissionPoint, - const Gaudi::XYZPoint& CoC, - const Gaudi::XYZPoint& virtDetPoint, + template< class TYPE, class POINT = Gaudi::XYZPoint, + std::size_t BISECTITS = 2, std::size_t NEWTONITS = 3 > + inline void solve( const POINT& emissionPoint, + const POINT& CoC, + const POINT& virtDetPoint, const TYPE radius, - Gaudi::XYZPoint& sphReflPoint ) const + POINT& sphReflPoint ) const { + using namespace std; // typedefs vectorised types - using Eigen3Vector = Eigen::Matrix< TYPE , 3 , 1 >; using Vec4x = typename std::conditional<std::is_same<TYPE,float>::value,Vec4f,Vec4d>::type; - using Vector = LHCb::Math::Eigen::XYZVector<TYPE>; - using Point = LHCb::Math::Eigen::XYZPoint<TYPE>; // vector from mirror centre of curvature to assumed emission point - const Vector evec( emissionPoint - CoC ); - const TYPE e2 = evec.dot(evec); + const auto evec( emissionPoint - CoC ); + const TYPE e2 = evec.Dot(evec); // vector from mirror centre of curvature to virtual detection point - const Vector dvec( virtDetPoint - CoC ); - const TYPE d2 = dvec.dot(dvec); + const auto dvec( virtDetPoint - CoC ); + const TYPE d2 = dvec.Dot(dvec); // various quantities needed to create quartic equation // see LHCB/98-040 section 3, equation 3 const TYPE ed2 = e2 * d2; //std::pow uses internal loop and causes branch misses and other inefficiencies //There might be a constant exponent pow function too, but i'm too lazy to check. - const TYPE cosgamma2 = ( ed2 > 0 ? std::pow(evec.dot(dvec),2)/ed2 : 1.0 ); + const TYPE cosgamma2 = ( ed2 > 0 ? pow(evec.Dot(dvec),2)/ed2 : TYPE(1.0) ); //const TYPE cosgamma2 = ( ed2 > 0.0f ? evec.dot(dvec)*evec.dot(dvec)/ed2 : 1.0f ); // vectorise 4 square roots into 1 - //TODO: This vectorized sqrt is questionable. There is a lot of overhead in gathering - //The different components via unaligned loads. It's probably not - //Faster than just computing the 4 square roots individually. const auto tmp_sqrt = sqrt( Vec4x( e2, d2, - cosgamma2 < 1.0f ? 1.0f-cosgamma2 : 0.0f, + cosgamma2 < TYPE(1.0) ? TYPE(1.0)-cosgamma2 : TYPE(0.0), cosgamma2 ) ); const TYPE e = tmp_sqrt[0]; const TYPE d = tmp_sqrt[1]; const TYPE singamma = tmp_sqrt[2]; const TYPE cosgamma = tmp_sqrt[3]; + //const TYPE e = std::sqrt(e2); + //const TYPE d = std::sqrt(d2); + //const TYPE singamma = std::sqrt( cosgamma2 < TYPE(1.0) ? TYPE(1.0)-cosgamma2 : TYPE(0.0) ); + //const TYPE cosgamma = std::sqrt(cosgamma2); const TYPE dx = d * cosgamma; const TYPE dy = d * singamma; @@ -114,15 +107,15 @@ namespace Rich const TYPE edx = e + dx; // Fill array for quartic equation - const auto a0 = 4.0f * ed2; + const auto a0 = TYPE(4.0) * ed2; //Newton solver doesn't care about a0 being not 1.0. Remove costly division and several multiplies. //This has some downsides though. The a-values are hovering around a numerical value of 10^15. single //precision float max is 10^37. A single square and some multiplies will push it over the limit of what //single precision float can handle. It's ok for the newton method, but Halley or higher order Housholder //will fail without this normalization. //const auto inv_a0 = ( a0 > 0 ? 1.0 / a0 : std::numeric_limits<TYPE>::max() ); - const TYPE dyrad2 = 2.0f * dy * radius; - const TYPE a1 = - ( 2.0f * dyrad2 * e2 );// * inv_a0; + const TYPE dyrad2 = TYPE(2.0) * dy * radius; + const TYPE a1 = - ( TYPE(2.0) * dyrad2 * e2 );// * inv_a0; const TYPE a2 = ( (dy2 * r2) + ( edx * edx * r2 ) - a0 );// * inv_a0; const TYPE a3 = ( dyrad2 * e * (e-dx) );// * inv_a0; const TYPE a4 = ( ( e2 - r2 ) * dy2 );// * inv_a0; @@ -154,16 +147,16 @@ namespace Rich //As far as we have tried with extreme values in the rich coordinate systems this is fine. //const Eigen::AngleAxis<TYPE> angleaxis( vdt::fast_asinf(sinbeta), // Eigen3Vector(n[0],n[1],n[2]) ); - const TYPE nx = (evec[1]*dvec[2]) - (evec[2]*dvec[1]); - const TYPE ny = (evec[2]*dvec[0]) - (evec[0]*dvec[2]); - const TYPE nz = (evec[0]*dvec[1]) - (evec[1]*dvec[0]); + const TYPE nx = (evec.y()*dvec.z()) - (evec.z()*dvec.y()); + const TYPE ny = (evec.z()*dvec.x()) - (evec.x()*dvec.z()); + const TYPE nz = (evec.x()*dvec.y()) - (evec.y()*dvec.x()); //const auto n = evec.cross3(dvec); //const auto norm = n.dot(n); const TYPE norm = nx*nx + ny*ny + nz*nz; - const TYPE norm_sqrt = std::sqrt(norm); + const TYPE norm_sqrt = sqrt(norm); const TYPE a = sinbeta * norm_sqrt; - const TYPE b = ( TYPE(1.0) - std::sqrt( TYPE(1.0) - (sinbeta*sinbeta) ) ); // <--(1-cos(beta)) + const TYPE b = ( TYPE(1.0) - sqrt( TYPE(1.0) - (sinbeta*sinbeta) ) ); // <--(1-cos(beta)) const TYPE enorm = radius/(e*norm); //Perform non-normalized rotation @@ -173,11 +166,12 @@ namespace Rich a*ny+b*nx*nz, -a*nx+b*ny*nz, norm+b*(-ny*ny-nx*nx) }; //re-normalize rotation and scale to radius in one step - const TYPE ex = enorm*(evec[0]*M[0]+evec[1]*M[3]+evec[2]*M[6]); - const TYPE ey = enorm*(evec[0]*M[1]+evec[1]*M[4]+evec[2]*M[7]); - const TYPE ez = enorm*(evec[0]*M[2]+evec[1]*M[5]+evec[2]*M[8]); + const TYPE ex = enorm*(evec.x()*M[0]+evec.y()*M[3]+evec.z()*M[6]); + const TYPE ey = enorm*(evec.x()*M[1]+evec.y()*M[4]+evec.z()*M[7]); + const TYPE ez = enorm*(evec.x()*M[2]+evec.y()*M[5]+evec.z()*M[8]); - sphReflPoint = ( CoC + Gaudi::XYZVector( ex, ey, ez ) ); + //sphReflPoint = ( CoC + Gaudi::XYZVector( ex, ey, ez ) ); + sphReflPoint = { CoC.x() + ex, CoC.y() + ey, CoC.z() + ez }; } private: @@ -190,7 +184,8 @@ namespace Rich //usable results template < class TYPE > - inline TYPE f4(const TYPE &a0, const TYPE &a1, const TYPE &a2, const TYPE &a3, const TYPE &a4, TYPE &x) const + inline TYPE f4(const TYPE &a0, const TYPE &a1, const TYPE &a2, + const TYPE &a3, const TYPE &a4, TYPE &x) const { //return (a0 * x*x*x*x + a1 * x*x*x + a2 * x*x + a3 * x + a4); //A bit more FMA friendly @@ -201,7 +196,7 @@ namespace Rich inline TYPE df4(const TYPE &a0, const TYPE &a1, const TYPE &a2, const TYPE &a3, TYPE &x) const { //return (4.0f*a0 * x*x*x + 3.0f*a1 * x*x + 2.0f*a2 * x + a3); - return (((4.0f * a0*x)+3.0f*a1)*x+2.0f*a2)*x+a3; + return ((( TYPE(4.0) * a0*x) + TYPE(3.0)*a1)*x+TYPE(2.0)*a2)*x+a3; } /** Horner's method to evaluate the polynomial and its derivatives with as little math operations as @@ -227,7 +222,7 @@ namespace Rich } //TODO: Check assembly to see if this is optimized away if DIFFGRADE is <= 2 - float l = 1.0; + TYPE l = 1.0; for ( unsigned int i = 2; i <= DIFFGRADE; ++i ) { l *= i; @@ -248,8 +243,8 @@ namespace Rich for ( unsigned int i = 0; i < ITER; ++i ) { evalPolyHorner<TYPE, 4, 3>(a, res, x0); - x0 -= ((6.0 * res[0]*res[1]*res[1] - 3.0 * res[0]*res[0]*res[2])/ - (6.0 * res[1]*res[1]*res[1] - 6.0 * res[0]*res[1]*res[2] + res[0]*res[0]*res[3])); + x0 -= ((TYPE(6.0) * res[0]*res[1]*res[1] - TYPE(3.0) * res[0]*res[0]*res[2])/ + (TYPE(6.0) * res[1]*res[1]*res[1] - TYPE(6.0) * res[0]*res[1]*res[2] + res[0]*res[0]*res[3])); //std::cout << x0 << ": " << res[0] << ", " << res[1] << ", " << res[2] << ", "<< res[3] << ", " << std::endl; } @@ -268,7 +263,7 @@ namespace Rich { //Starting value for housholder iteration. Empirically values seem to be //between 0 0and 0.4 so we chose the value in the middle as starting point - TYPE x0 = 0.2f; + TYPE x0 = TYPE(0.2); TYPE a[5] = {1.0f, a0, a1, a2, a3}; //std::cout << "Polynomial: " << std::endl; -- GitLab From 59d0bb8dc714708a5a3067550e64bf8ef9f568fd Mon Sep 17 00:00:00 2001 From: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Sat, 4 Mar 2017 18:10:11 +0100 Subject: [PATCH 38/68] increase number of test photons --- Rich/RichRecTests/src/PhotonReco/main.icpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Rich/RichRecTests/src/PhotonReco/main.icpp b/Rich/RichRecTests/src/PhotonReco/main.icpp index 07eb3eb80b..28ff543be4 100644 --- a/Rich/RichRecTests/src/PhotonReco/main.icpp +++ b/Rich/RichRecTests/src/PhotonReco/main.icpp @@ -86,7 +86,7 @@ unsigned long long int __attribute__((noinline)) solve( const Data::Vector & dat int main ( int /*argc*/, char** /*argv*/ ) { - const unsigned int nPhotons = 1e4; + const unsigned int nPhotons = 1e5; Data::Vector dataV; dataV.reserve( nPhotons ); -- GitLab From b2c4b91abad37df452d85877d8b1cbe5aba954bd Mon Sep 17 00:00:00 2001 From: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Sat, 4 Mar 2017 18:19:46 +0100 Subject: [PATCH 39/68] Reorder template types --- Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h b/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h index 689c3d3c34..1212d04545 100755 --- a/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h +++ b/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h @@ -11,9 +11,6 @@ // Gaudi #include "GaudiKernel/Kernel.h" -#include "GaudiKernel/Transform3DTypes.h" -#include "GaudiKernel/Point3DTypes.h" -#include "GaudiKernel/Vector3DTypes.h" // VectorClass #include "VectorClass/vectorclass.h" @@ -59,8 +56,9 @@ namespace Rich * @retval true Calculation was successful. sphReflPoint is valid. * @retval false Calculation failed. sphReflPoint is not valid. */ - template< class TYPE, class POINT = Gaudi::XYZPoint, - std::size_t BISECTITS = 2, std::size_t NEWTONITS = 3 > + template< class TYPE, + std::size_t BISECTITS = 2, std::size_t NEWTONITS = 3, + class POINT = Gaudi::XYZPoint > inline void solve( const POINT& emissionPoint, const POINT& CoC, const POINT& virtDetPoint, -- GitLab From 95224bb46434622ea2715722591d3d95d7b30496 Mon Sep 17 00:00:00 2001 From: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Sat, 4 Mar 2017 18:20:19 +0100 Subject: [PATCH 40/68] Add headers removed from quartic solver --- Rich/RichRecTests/src/PhotonReco/main.icpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Rich/RichRecTests/src/PhotonReco/main.icpp b/Rich/RichRecTests/src/PhotonReco/main.icpp index 28ff543be4..809b5abac8 100644 --- a/Rich/RichRecTests/src/PhotonReco/main.icpp +++ b/Rich/RichRecTests/src/PhotonReco/main.icpp @@ -1,4 +1,9 @@ +// Gaudi +//#include "GaudiKernel/Transform3DTypes.h" +#include "GaudiKernel/Point3DTypes.h" +#include "GaudiKernel/Vector3DTypes.h" + // Quartic Solver #include "RichRecUtils/QuarticSolverNewton.h" -- GitLab From 4039ee37313636bbbac5ec2daf3f50d8c744899b Mon Sep 17 00:00:00 2001 From: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Sat, 4 Mar 2017 20:11:41 +0100 Subject: [PATCH 41/68] Set ray traced photons back to 100 --- .../python/RichFutureRecSys/ConfiguredRichReco.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Rich/RichFutureRecSys/python/RichFutureRecSys/ConfiguredRichReco.py b/Rich/RichFutureRecSys/python/RichFutureRecSys/ConfiguredRichReco.py index c21660c283..e99f4138a7 100644 --- a/Rich/RichFutureRecSys/python/RichFutureRecSys/ConfiguredRichReco.py +++ b/Rich/RichFutureRecSys/python/RichFutureRecSys/ConfiguredRichReco.py @@ -137,7 +137,7 @@ def RichRecoSequence( GroupName = "", # Optional name given to this group. preloadGeometry = False, # Number points for mass hypothesis ring ray tracing - NRingPoints = ( 96, 96, 96 ), + NRingPoints = ( 100, 100, 100 ), # Track Extrapolator type trackExtrapolator = "TrackRungeKuttaExtrapolator", -- GitLab From d5b40736273b886951dd4556271ad0776ccb7d60 Mon Sep 17 00:00:00 2001 From: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Sat, 4 Mar 2017 21:37:25 +0100 Subject: [PATCH 42/68] Turn off bad photon check --- .../src/RichRayTraceCherenkovCones.cpp | 13 ++++++++----- .../src/RichRayTraceCherenkovCones.h | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovCones.cpp b/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovCones.cpp index f411bee2bd..98ab9292e9 100644 --- a/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovCones.cpp +++ b/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovCones.cpp @@ -122,6 +122,9 @@ RayTraceCherenkovCones::operator()( const LHCb::RichTrackSegment::Vector& segmen P.cosPhi, P.sinPhi ) ); } + // Count the number of good photons + unsigned int nOK(0); + // Which ray tracing to run if ( m_useVectorised ) { @@ -131,7 +134,7 @@ RayTraceCherenkovCones::operator()( const LHCb::RichTrackSegment::Vector& segmen m_rayTrace.get()->traceToDetector( emissionPoint, vects, segment, m_traceModeRad[rad] ); // loop over the results and fill - unsigned int nOK(0), nPhot(0); + unsigned int nPhot(0); for ( const auto && data : Ranges::ConstZip(results,m_cosSinPhiV[rad]) ) { const auto & res = std::get<0>(data); @@ -160,7 +163,7 @@ RayTraceCherenkovCones::operator()( const LHCb::RichTrackSegment::Vector& segmen { // Loop over the directions and ray trace them using the scalar method - unsigned int nOK(0), nPhot(0); + unsigned int nPhot(0); for ( const auto && data : Ranges::ConstZip(vects,m_cosSinPhiV[rad]) ) { const auto & photDir = std::get<0>(data); @@ -193,10 +196,10 @@ RayTraceCherenkovCones::operator()( const LHCb::RichTrackSegment::Vector& segmen if ( 0 == nOK && nPhot >= m_nBailout[rad] ) break; } - // if no good hits empty the container - if ( 0 == nOK ) { rings[id].clear(); } - } + + // if no good hits empty the container + //if ( 0 == nOK ) { rings[id].clear(); } } diff --git a/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovCones.h b/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovCones.h index 9b653e9356..93a22334a6 100644 --- a/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovCones.h +++ b/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovCones.h @@ -124,7 +124,7 @@ namespace Rich /// Use the scalar or vector ray tracing Gaudi::Property<bool> m_useVectorised - { this, "UseVectorisedRayTracing", true }; + { this, "UseVectorisedRayTracing", false }; /// Ray tracing tool ToolHandle<const IRayTracing> m_rayTrace -- GitLab From c7c6a4dc17f44a08ef139e00cf2d510bca657f5e Mon Sep 17 00:00:00 2001 From: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Sat, 4 Mar 2017 22:19:01 +0100 Subject: [PATCH 43/68] Small clean up --- Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h b/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h index 1212d04545..6d14df6709 100755 --- a/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h +++ b/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h @@ -263,7 +263,7 @@ namespace Rich //between 0 0and 0.4 so we chose the value in the middle as starting point TYPE x0 = TYPE(0.2); - TYPE a[5] = {1.0f, a0, a1, a2, a3}; + TYPE a[5] = { TYPE(1.0), a0, a1, a2, a3}; //std::cout << "Polynomial: " << std::endl; //std::cout << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ", " << a[4] << std::endl; x0 = householder<TYPE, ITER>(a, x0); @@ -301,7 +301,7 @@ namespace Rich u = oppositeSign ? m : u; //std::cout << l.extract(0) << ", " << m.extract(0) << ", " << u.extract(0) << ", " << oppositeSign.extract(0) << std::endl; //0.4 instead of 0.5 to speed up convergence. Most roots seem to be closer to 0 than to the extreme end - m = (u + l) * 0.4; + m = (u + l) * TYPE(0.4); } //Newton for the rest @@ -320,8 +320,7 @@ namespace Rich { evalPolyHorner<TYPE, 4, 1>(a, res, m); //epsilon = f4(a0,a1,a2,a3,a4,x) / df4(a0,a1,a2,a3,x); - TYPE epsilon = res[0] / res[1]; - m -= gain * epsilon; + m -= gain * ( res[0] / res[1] ); } return m; -- GitLab From e72174a3d354ddd325f9a76ff6fa82334859a98b Mon Sep 17 00:00:00 2001 From: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Sat, 4 Mar 2017 23:33:49 +0100 Subject: [PATCH 44/68] Small improvements --- .../src/RichRayTraceCherenkovCones.cpp | 3 ++ .../src/RichRayTraceCherenkovCones.h | 2 +- .../RichRecUtils/QuarticSolverNewton.h | 33 ++++++++++--------- 3 files changed, 22 insertions(+), 16 deletions(-) diff --git a/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovCones.cpp b/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovCones.cpp index 98ab9292e9..64cc4a39e0 100644 --- a/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovCones.cpp +++ b/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovCones.cpp @@ -155,6 +155,9 @@ RayTraceCherenkovCones::operator()( const LHCb::RichTrackSegment::Vector& segmen // count raytraces that are in HPD panel if ( res.result >= LHCb::RichTraceMode::InHPDPanel ) { ++nOK; } + + // bailout check + if ( 0 == nOK && nPhot >= m_nBailout[rad] ) break; } diff --git a/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovCones.h b/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovCones.h index 93a22334a6..9b653e9356 100644 --- a/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovCones.h +++ b/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovCones.h @@ -124,7 +124,7 @@ namespace Rich /// Use the scalar or vector ray tracing Gaudi::Property<bool> m_useVectorised - { this, "UseVectorisedRayTracing", false }; + { this, "UseVectorisedRayTracing", true }; /// Ray tracing tool ToolHandle<const IRayTracing> m_rayTrace diff --git a/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h b/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h index 6d14df6709..79fa0ffbec 100755 --- a/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h +++ b/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h @@ -105,7 +105,7 @@ namespace Rich const TYPE edx = e + dx; // Fill array for quartic equation - const auto a0 = TYPE(4.0) * ed2; + const TYPE a0 = TYPE(4.0) * ed2; //Newton solver doesn't care about a0 being not 1.0. Remove costly division and several multiplies. //This has some downsides though. The a-values are hovering around a numerical value of 10^15. single //precision float max is 10^37. A single square and some multiplies will push it over the limit of what @@ -145,23 +145,26 @@ namespace Rich //As far as we have tried with extreme values in the rich coordinate systems this is fine. //const Eigen::AngleAxis<TYPE> angleaxis( vdt::fast_asinf(sinbeta), // Eigen3Vector(n[0],n[1],n[2]) ); - const TYPE nx = (evec.y()*dvec.z()) - (evec.z()*dvec.y()); - const TYPE ny = (evec.z()*dvec.x()) - (evec.x()*dvec.z()); - const TYPE nz = (evec.x()*dvec.y()) - (evec.y()*dvec.x()); + const TYPE nx = (evec.y()*dvec.z()) - (evec.z()*dvec.y()); + const TYPE ny = (evec.z()*dvec.x()) - (evec.x()*dvec.z()); + const TYPE nz = (evec.x()*dvec.y()) - (evec.y()*dvec.x()); + const TYPE nx2 = nx*nx; + const TYPE ny2 = ny*ny; + const TYPE nz2 = nz*nz; //const auto n = evec.cross3(dvec); //const auto norm = n.dot(n); - const TYPE norm = nx*nx + ny*ny + nz*nz; + const TYPE norm = nx2 + ny2 + nz2; const TYPE norm_sqrt = sqrt(norm); - const TYPE a = sinbeta * norm_sqrt; - const TYPE b = ( TYPE(1.0) - sqrt( TYPE(1.0) - (sinbeta*sinbeta) ) ); // <--(1-cos(beta)) + const TYPE a = sinbeta * norm_sqrt; + const TYPE b = ( TYPE(1.0) - sqrt( TYPE(1.0) - (sinbeta*sinbeta) ) ); // <--(1-cos(beta)) const TYPE enorm = radius/(e*norm); //Perform non-normalized rotation const std::array<TYPE,9> M = - { norm + b*(-nz*nz-ny*ny), a*nz+b*nx*ny, -a*ny+b*nx*nz, - -a*nz+b*nx*ny, norm+b*(-nx*nx-nz*nz), a*nx+b*ny*nz, - a*ny+b*nx*nz, -a*nx+b*ny*nz, norm+b*(-ny*ny-nx*nx) }; + { norm + b*(-nz2-ny2), a*nz+b*nx*ny, -a*ny+b*nx*nz, + -a*nz+b*nx*ny, norm+b*(-nx2-nz2), a*nx+b*ny*nz, + a*ny+b*nx*nz, -a*nx+b*ny*nz, norm+b*(-ny2-nx2) }; //re-normalize rotation and scale to radius in one step const TYPE ex = enorm*(evec.x()*M[0]+evec.y()*M[3]+evec.z()*M[6]); @@ -194,7 +197,7 @@ namespace Rich inline TYPE df4(const TYPE &a0, const TYPE &a1, const TYPE &a2, const TYPE &a3, TYPE &x) const { //return (4.0f*a0 * x*x*x + 3.0f*a1 * x*x + 2.0f*a2 * x + a3); - return ((( TYPE(4.0) * a0*x) + TYPE(3.0)*a1)*x+TYPE(2.0)*a2)*x+a3; + return ( ( ( ( TYPE(4.0) * a0*x ) + TYPE(3.0) * a1 ) * x + ( TYPE(2.0) * a2 ) ) * x ) + a3; } /** Horner's method to evaluate the polynomial and its derivatives with as little math operations as @@ -204,12 +207,12 @@ namespace Rich template < class TYPE, std::size_t ORDER = 4, std::size_t DIFFGRADE = 3 > inline void evalPolyHorner(const TYPE (&a)[ORDER+1], TYPE (&res)[DIFFGRADE+1], TYPE x) const { - for ( unsigned int i = 0; i <= DIFFGRADE; ++i ) + for ( std::size_t i = 0; i <= DIFFGRADE; ++i ) { res[i] = a[0]; } - for ( unsigned int j = 1; j <= ORDER; ++j ) + for ( std::size_t j = 1; j <= ORDER; ++j ) { res[0] = res[0] * x + a[j]; int l = (ORDER - j) > DIFFGRADE ? DIFFGRADE : ORDER - j; @@ -221,7 +224,7 @@ namespace Rich //TODO: Check assembly to see if this is optimized away if DIFFGRADE is <= 2 TYPE l = 1.0; - for ( unsigned int i = 2; i <= DIFFGRADE; ++i ) + for ( std::size_t i = 2; i <= DIFFGRADE; ++i ) { l *= i; res[i] = res[i] * l; @@ -238,7 +241,7 @@ namespace Rich inline TYPE householder(const TYPE (&a)[5], TYPE x0) const { TYPE res[4]; - for ( unsigned int i = 0; i < ITER; ++i ) + for ( std::size_t i = 0; i < ITER; ++i ) { evalPolyHorner<TYPE, 4, 3>(a, res, x0); x0 -= ((TYPE(6.0) * res[0]*res[1]*res[1] - TYPE(3.0) * res[0]*res[0]*res[2])/ -- GitLab From 2206e3c40789ec575f7f88b3f6c92c61fa2fb992 Mon Sep 17 00:00:00 2001 From: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Sat, 4 Mar 2017 23:55:35 +0100 Subject: [PATCH 45/68] cache a few computations --- .../RichRecUtils/QuarticSolverNewton.h | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h b/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h index 79fa0ffbec..663fce6572 100755 --- a/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h +++ b/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h @@ -83,7 +83,7 @@ namespace Rich const TYPE ed2 = e2 * d2; //std::pow uses internal loop and causes branch misses and other inefficiencies //There might be a constant exponent pow function too, but i'm too lazy to check. - const TYPE cosgamma2 = ( ed2 > 0 ? pow(evec.Dot(dvec),2)/ed2 : TYPE(1.0) ); + const TYPE cosgamma2 = ( ed2 > TYPE(0.0) ? pow(evec.Dot(dvec),2)/ed2 : TYPE(1.0) ); //const TYPE cosgamma2 = ( ed2 > 0.0f ? evec.dot(dvec)*evec.dot(dvec)/ed2 : 1.0f ); // vectorise 4 square roots into 1 const auto tmp_sqrt = sqrt( Vec4x( e2, d2, @@ -148,24 +148,29 @@ namespace Rich const TYPE nx = (evec.y()*dvec.z()) - (evec.z()*dvec.y()); const TYPE ny = (evec.z()*dvec.x()) - (evec.x()*dvec.z()); const TYPE nz = (evec.x()*dvec.y()) - (evec.y()*dvec.x()); + const TYPE nx2 = nx*nx; const TYPE ny2 = ny*ny; const TYPE nz2 = nz*nz; - //const auto n = evec.cross3(dvec); - //const auto norm = n.dot(n); + + const TYPE nxny = nx*ny; + const TYPE nxnz = nx*nz; + const TYPE nynz = ny*nz; + const TYPE norm = nx2 + ny2 + nz2; const TYPE norm_sqrt = sqrt(norm); - const TYPE a = sinbeta * norm_sqrt; - const TYPE b = ( TYPE(1.0) - sqrt( TYPE(1.0) - (sinbeta*sinbeta) ) ); // <--(1-cos(beta)) - const TYPE enorm = radius/(e*norm); + const TYPE a = sinbeta * norm_sqrt; + const TYPE sinbeta2 = sinbeta * sinbeta; + const TYPE b = ( sinbeta2 < TYPE(1.0) ? ( TYPE(1.0) - sqrt( TYPE(1.0) - sinbeta2 ) ) : TYPE(1.0) ); + const TYPE enorm = radius/(e*norm); //Perform non-normalized rotation const std::array<TYPE,9> M = - { norm + b*(-nz2-ny2), a*nz+b*nx*ny, -a*ny+b*nx*nz, - -a*nz+b*nx*ny, norm+b*(-nx2-nz2), a*nx+b*ny*nz, - a*ny+b*nx*nz, -a*nx+b*ny*nz, norm+b*(-ny2-nx2) }; - + { norm - b*(nz2+ny2), a*nz+b*nxny, -a*ny+b*nxnz, + -a*nz+b*nxny, norm - b*(nx2+nz2), a*nx+b*nynz, + a*ny+b*nxnz, -a*nx+b*nynz, norm-b*(ny2+nx2) }; + //re-normalize rotation and scale to radius in one step const TYPE ex = enorm*(evec.x()*M[0]+evec.y()*M[3]+evec.z()*M[6]); const TYPE ey = enorm*(evec.x()*M[1]+evec.y()*M[4]+evec.z()*M[7]); @@ -190,7 +195,7 @@ namespace Rich { //return (a0 * x*x*x*x + a1 * x*x*x + a2 * x*x + a3 * x + a4); //A bit more FMA friendly - return ((((a0*x)+a1)*x+a2)*x+a3)*x+a4; + return ( ( ( (a0*x) + a1 ) *x + a2 ) *x + a3 ) *x + a4; } template < class TYPE > -- GitLab From cfa96a2e046968a9b24f508adb660c9a0914bf47 Mon Sep 17 00:00:00 2001 From: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Sun, 5 Mar 2017 00:01:29 +0100 Subject: [PATCH 46/68] cache a few computations --- .../RichRecUtils/QuarticSolverNewton.h | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h b/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h index 663fce6572..e86da121e7 100755 --- a/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h +++ b/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h @@ -143,8 +143,6 @@ namespace Rich //Divisions by normalizing only once at the very end //Again, care has to be taken since we are close to float_max here without immediate normalization. //As far as we have tried with extreme values in the rich coordinate systems this is fine. - //const Eigen::AngleAxis<TYPE> angleaxis( vdt::fast_asinf(sinbeta), - // Eigen3Vector(n[0],n[1],n[2]) ); const TYPE nx = (evec.y()*dvec.z()) - (evec.z()*dvec.y()); const TYPE ny = (evec.z()*dvec.x()) - (evec.x()*dvec.z()); const TYPE nz = (evec.x()*dvec.y()) - (evec.y()*dvec.x()); @@ -153,10 +151,6 @@ namespace Rich const TYPE ny2 = ny*ny; const TYPE nz2 = nz*nz; - const TYPE nxny = nx*ny; - const TYPE nxnz = nx*nz; - const TYPE nynz = ny*nz; - const TYPE norm = nx2 + ny2 + nz2; const TYPE norm_sqrt = sqrt(norm); @@ -165,11 +159,15 @@ namespace Rich const TYPE b = ( sinbeta2 < TYPE(1.0) ? ( TYPE(1.0) - sqrt( TYPE(1.0) - sinbeta2 ) ) : TYPE(1.0) ); const TYPE enorm = radius/(e*norm); + const TYPE bnxny = b*nx*ny; + const TYPE bnxnz = b*nx*nz; + const TYPE bnynz = b*ny*nz; + //Perform non-normalized rotation const std::array<TYPE,9> M = - { norm - b*(nz2+ny2), a*nz+b*nxny, -a*ny+b*nxnz, - -a*nz+b*nxny, norm - b*(nx2+nz2), a*nx+b*nynz, - a*ny+b*nxnz, -a*nx+b*nynz, norm-b*(ny2+nx2) }; + { norm - b*(nz2+ny2), a*nz+bnxny, -a*ny+bnxnz, + -a*nz+bnxny, norm - b*(nx2+nz2), a*nx+bnynz, + a*ny+bnxnz, -a*nx+bnynz, norm-b*(ny2+nx2) }; //re-normalize rotation and scale to radius in one step const TYPE ex = enorm*(evec.x()*M[0]+evec.y()*M[3]+evec.z()*M[6]); @@ -195,7 +193,7 @@ namespace Rich { //return (a0 * x*x*x*x + a1 * x*x*x + a2 * x*x + a3 * x + a4); //A bit more FMA friendly - return ( ( ( (a0*x) + a1 ) *x + a2 ) *x + a3 ) *x + a4; + return ( ( ( ( ( ( (a0*x) + a1 ) * x ) + a2 ) * x ) + a3 ) * x ) + a4; } template < class TYPE > -- GitLab From fd5fc1138eaee7db0363ed1be9836feb032f9140 Mon Sep 17 00:00:00 2001 From: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Sun, 5 Mar 2017 00:05:44 +0100 Subject: [PATCH 47/68] cache a few computations --- Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h b/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h index e86da121e7..39e5420262 100755 --- a/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h +++ b/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h @@ -301,7 +301,7 @@ namespace Rich TYPE res[2]; for ( std::size_t i = 0; i <= BISECTITS; ++i ) { - auto oppositeSign = std::signbit(f4(a0,a1,a2,a3,a4,m) * f4(a0,a1,a2,a3,a4,l)); + const auto oppositeSign = std::signbit(f4(a0,a1,a2,a3,a4,m) * f4(a0,a1,a2,a3,a4,l)); l = oppositeSign ? l : m; u = oppositeSign ? m : u; -- GitLab From de148cfe3399dd75512b42aa8961bb637d69144f Mon Sep 17 00:00:00 2001 From: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Sun, 5 Mar 2017 00:43:53 +0100 Subject: [PATCH 48/68] clean up a little --- .../RichRecUtils/QuarticSolverNewton.h | 36 +++++++------------ 1 file changed, 13 insertions(+), 23 deletions(-) diff --git a/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h b/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h index 39e5420262..fff91e926c 100755 --- a/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h +++ b/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h @@ -80,11 +80,8 @@ namespace Rich // various quantities needed to create quartic equation // see LHCB/98-040 section 3, equation 3 - const TYPE ed2 = e2 * d2; - //std::pow uses internal loop and causes branch misses and other inefficiencies - //There might be a constant exponent pow function too, but i'm too lazy to check. + const TYPE ed2 = e2 * d2; const TYPE cosgamma2 = ( ed2 > TYPE(0.0) ? pow(evec.Dot(dvec),2)/ed2 : TYPE(1.0) ); - //const TYPE cosgamma2 = ( ed2 > 0.0f ? evec.dot(dvec)*evec.dot(dvec)/ed2 : 1.0f ); // vectorise 4 square roots into 1 const auto tmp_sqrt = sqrt( Vec4x( e2, d2, cosgamma2 < TYPE(1.0) ? TYPE(1.0)-cosgamma2 : TYPE(0.0), @@ -93,6 +90,7 @@ namespace Rich const TYPE d = tmp_sqrt[1]; const TYPE singamma = tmp_sqrt[2]; const TYPE cosgamma = tmp_sqrt[3]; + // scalar versions //const TYPE e = std::sqrt(e2); //const TYPE d = std::sqrt(d2); //const TYPE singamma = std::sqrt( cosgamma2 < TYPE(1.0) ? TYPE(1.0)-cosgamma2 : TYPE(0.0) ); @@ -188,16 +186,16 @@ namespace Rich //usable results template < class TYPE > - inline TYPE f4(const TYPE &a0, const TYPE &a1, const TYPE &a2, - const TYPE &a3, const TYPE &a4, TYPE &x) const + inline TYPE f4( const TYPE &a0, const TYPE &a1, const TYPE &a2, + const TYPE &a3, const TYPE &a4, TYPE &x ) const { //return (a0 * x*x*x*x + a1 * x*x*x + a2 * x*x + a3 * x + a4); //A bit more FMA friendly - return ( ( ( ( ( ( (a0*x) + a1 ) * x ) + a2 ) * x ) + a3 ) * x ) + a4; + return ( ( ( ( ( ( ( a0 * x ) + a1 ) * x ) + a2 ) * x ) + a3 ) * x ) + a4; } template < class TYPE > - inline TYPE df4(const TYPE &a0, const TYPE &a1, const TYPE &a2, const TYPE &a3, TYPE &x) const + inline TYPE df4( const TYPE &a0, const TYPE &a1, const TYPE &a2, const TYPE &a3, TYPE &x ) const { //return (4.0f*a0 * x*x*x + 3.0f*a1 * x*x + 2.0f*a2 * x + a3); return ( ( ( ( TYPE(4.0) * a0*x ) + TYPE(3.0) * a1 ) * x + ( TYPE(2.0) * a2 ) ) * x ) + a3; @@ -208,7 +206,7 @@ namespace Rich * that is free from branches and optimized for the grade of polynomial and derivatives as necessary. */ template < class TYPE, std::size_t ORDER = 4, std::size_t DIFFGRADE = 3 > - inline void evalPolyHorner(const TYPE (&a)[ORDER+1], TYPE (&res)[DIFFGRADE+1], TYPE x) const + inline void evalPolyHorner( const TYPE (&a)[ORDER+1], TYPE (&res)[DIFFGRADE+1], const TYPE x ) const { for ( std::size_t i = 0; i <= DIFFGRADE; ++i ) { @@ -218,7 +216,7 @@ namespace Rich for ( std::size_t j = 1; j <= ORDER; ++j ) { res[0] = res[0] * x + a[j]; - int l = (ORDER - j) > DIFFGRADE ? DIFFGRADE : ORDER - j; + const int l = (ORDER - j) > DIFFGRADE ? DIFFGRADE : ORDER - j; for ( int i = 1; i <= l ; ++i ) { res[i] = res[i] * x + res[i-1]; @@ -249,8 +247,6 @@ namespace Rich evalPolyHorner<TYPE, 4, 3>(a, res, x0); x0 -= ((TYPE(6.0) * res[0]*res[1]*res[1] - TYPE(3.0) * res[0]*res[0]*res[2])/ (TYPE(6.0) * res[1]*res[1]*res[1] - TYPE(6.0) * res[0]*res[1]*res[2] + res[0]*res[0]*res[3])); - //std::cout << x0 << ": " << res[0] << ", " << res[1] << ", " << res[2] << ", "<< res[3] << ", " << std::endl; - } return x0; } @@ -268,13 +264,8 @@ namespace Rich //Starting value for housholder iteration. Empirically values seem to be //between 0 0and 0.4 so we chose the value in the middle as starting point TYPE x0 = TYPE(0.2); - - TYPE a[5] = { TYPE(1.0), a0, a1, a2, a3}; - //std::cout << "Polynomial: " << std::endl; - //std::cout << a[0] << ", " << a[1] << ", " << a[2] << ", " << a[3] << ", " << a[4] << std::endl; - x0 = householder<TYPE, ITER>(a, x0); - - return x0; + TYPE a[5] = { TYPE(1.0), a0, a1, a2, a3 }; + return householder<TYPE, ITER>( a, x0 ); } /** Newton-Rhapson method for calculating the root of the rich polynomial. It uses the bisection method in the beginning @@ -294,7 +285,7 @@ namespace Rich const TYPE& a4 ) const { //Use N steps of bisection method to find starting point for newton - TYPE l(0); + TYPE l(0.0); TYPE u(0.5); TYPE m(0.2); //We start a bit off center since the distribution of roots tends to be more to the left side const TYPE a[5] = {a0, a1, a2, a3, a4}; @@ -305,9 +296,8 @@ namespace Rich l = oppositeSign ? l : m; u = oppositeSign ? m : u; - //std::cout << l.extract(0) << ", " << m.extract(0) << ", " << u.extract(0) << ", " << oppositeSign.extract(0) << std::endl; //0.4 instead of 0.5 to speed up convergence. Most roots seem to be closer to 0 than to the extreme end - m = (u + l) * TYPE(0.4); + m = ( u + l ) * TYPE(0.4); } //Newton for the rest @@ -324,7 +314,7 @@ namespace Rich for ( std::size_t i = 0; i <= NEWTONITS; ++i ) { - evalPolyHorner<TYPE, 4, 1>(a, res, m); + evalPolyHorner<TYPE, 4, 1>( a, res, m ); //epsilon = f4(a0,a1,a2,a3,a4,x) / df4(a0,a1,a2,a3,x); m -= gain * ( res[0] / res[1] ); } -- GitLab From 23c8ac0f9dbc0fc71e2dd20dc6699caab0264055 Mon Sep 17 00:00:00 2001 From: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Sun, 5 Mar 2017 13:30:22 +0100 Subject: [PATCH 49/68] Reduce number of ray traced photons from 100 to 96 so as to fit perfectly into a SIMD vector --- .../python/RichFutureRecSys/ConfiguredRichReco.py | 2 +- .../src/RichRayTraceCherenkovCones.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Rich/RichFutureRecSys/python/RichFutureRecSys/ConfiguredRichReco.py b/Rich/RichFutureRecSys/python/RichFutureRecSys/ConfiguredRichReco.py index e99f4138a7..c21660c283 100644 --- a/Rich/RichFutureRecSys/python/RichFutureRecSys/ConfiguredRichReco.py +++ b/Rich/RichFutureRecSys/python/RichFutureRecSys/ConfiguredRichReco.py @@ -137,7 +137,7 @@ def RichRecoSequence( GroupName = "", # Optional name given to this group. preloadGeometry = False, # Number points for mass hypothesis ring ray tracing - NRingPoints = ( 100, 100, 100 ), + NRingPoints = ( 96, 96, 96 ), # Track Extrapolator type trackExtrapolator = "TrackRungeKuttaExtrapolator", diff --git a/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovCones.h b/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovCones.h index 9b653e9356..26dd924732 100644 --- a/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovCones.h +++ b/Rich/RichFutureRecTrackAlgorithms/src/RichRayTraceCherenkovCones.h @@ -100,7 +100,7 @@ namespace Rich /// Number of points to ray trace on each ring, for each radiator Gaudi::Property< RadiatorArray<unsigned int> > m_nPoints - { this, "NRingPoints", { 100u, 100u, 100u } }; + { this, "NRingPoints", { 96u, 96u, 96u } }; /// Bailout number RadiatorArray<unsigned int> m_nBailout = {{}}; -- GitLab From 6eaef4e27238ef08fe2fe9d701d6d2837db03d66 Mon Sep 17 00:00:00 2001 From: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Sun, 5 Mar 2017 13:31:03 +0100 Subject: [PATCH 50/68] Reduce number of NR iterations for first stage of photon reco where best precision is not required --- .../src/RichQuarticPhotonReco.cpp | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/Rich/RichFutureRecPhotonAlgorithms/src/RichQuarticPhotonReco.cpp b/Rich/RichFutureRecPhotonAlgorithms/src/RichQuarticPhotonReco.cpp index 5959114866..6616869b50 100644 --- a/Rich/RichFutureRecPhotonAlgorithms/src/RichQuarticPhotonReco.cpp +++ b/Rich/RichFutureRecPhotonAlgorithms/src/RichQuarticPhotonReco.cpp @@ -456,11 +456,11 @@ QuarticPhotonReco::operator()( const LHCb::RichTrackSegment::Vector& segments, virtDetPoint = gloPos - 2.0 * distance * secSegment->centreNormal(); // solve the quartic using the new data - m_quarticSolver.solve<double>( emissionPoint, - sphSegment->centreOfCurvature(), - virtDetPoint, - sphSegment->radius(), - sphReflPoint ); + m_quarticSolver.solve<double,2,3>( emissionPoint, + sphSegment->centreOfCurvature(), + virtDetPoint, + sphSegment->radius(), + sphReflPoint ); // (re)find the spherical mirror segment // CRJ - Is this needed ? @@ -507,11 +507,11 @@ QuarticPhotonReco::operator()( const LHCb::RichTrackSegment::Vector& segments, virtDetPoint = gloPos - 2.0 * distance * plane.Normal(); // solve the quartic using the new data - m_quarticSolver.solve<double>( emissionPoint, - sphSegment->centreOfCurvature(), - virtDetPoint, - sphSegment->radius(), - sphReflPoint ); + m_quarticSolver.solve<double,2,3>( emissionPoint, + sphSegment->centreOfCurvature(), + virtDetPoint, + sphSegment->radius(), + sphReflPoint ); // (re)find the spherical mirror segment sphSegment = m_mirrorSegFinder.get()->findSphMirror( rich, side, sphReflPoint ); @@ -663,11 +663,11 @@ findMirrorData( const Rich::DetectorType rich, Gaudi::XYZPoint& secReflPoint ) const { // solve quartic equation with nominal values and find spherical mirror reflection point - m_quarticSolver.solve<double>( emissionPoint, - m_rich[rich]->nominalCentreOfCurvature(side), - virtDetPoint, - m_rich[rich]->sphMirrorRadius(), - sphReflPoint ); + m_quarticSolver.solve<double,2,2>( emissionPoint, + m_rich[rich]->nominalCentreOfCurvature(side), + virtDetPoint, + m_rich[rich]->sphMirrorRadius(), + sphReflPoint ); // find the spherical mirror segment sphSegment = m_mirrorSegFinder.get()->findSphMirror( rich, side, sphReflPoint ); // Search for the secondary segment -- GitLab From c8dd66e31a7784800c3fa525371e7d2fe340e46d Mon Sep 17 00:00:00 2001 From: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Sun, 5 Mar 2017 17:05:11 +0100 Subject: [PATCH 51/68] Propagate template parameters to NR method --- Rich/RichRecTests/src/PhotonReco/main.icpp | 10 +++++----- Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Rich/RichRecTests/src/PhotonReco/main.icpp b/Rich/RichRecTests/src/PhotonReco/main.icpp index 809b5abac8..91a02a4784 100644 --- a/Rich/RichRecTests/src/PhotonReco/main.icpp +++ b/Rich/RichRecTests/src/PhotonReco/main.icpp @@ -61,11 +61,11 @@ public: template< class TYPE > inline void solve( const Data& data ) { - qSolver.solve<TYPE>( data.emissPnt, - data.centOfCurv, - data.virtDetPoint, - data.radius, - sphReflPoint ); + qSolver.solve<TYPE,2,2>( data.emissPnt, + data.centOfCurv, + data.virtDetPoint, + data.radius, + sphReflPoint ); } template< class TYPE > diff --git a/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h b/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h index fff91e926c..097bfeec93 100755 --- a/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h +++ b/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h @@ -124,7 +124,7 @@ namespace Rich // ); //Use optimized newton solver on quartic equation. - const auto sinbeta = solve_quartic_newton_RICH( a0, a1, a2, a3, a4 ); + const auto sinbeta = solve_quartic_newton_RICH<TYPE,BISECTITS,NEWTONITS>( a0, a1, a2, a3, a4 ); //TODO: This method should be better but has problems still for some reasons //const auto sinbeta = solve_quartic_housholder_RICH<TYPE, 3>(a1, a2, a3, a4); @@ -255,7 +255,7 @@ namespace Rich * polynomial have to be normalized. They are typically around 10^15 and floating point overflows will occur in here if these * large values are used. */ - template < class TYPE , std::size_t ITER = 3 > + template < class TYPE, std::size_t ITER = 3 > inline TYPE solve_quartic_housholder_RICH( const TYPE& a0, const TYPE& a1, const TYPE& a2, -- GitLab From 0b27591e9aabf9e3dbb131b1acbd06901681cb33 Mon Sep 17 00:00:00 2001 From: Jeroen van Tilburg <Jeroen.van.Tilburg@cern.ch> Date: Mon, 6 Mar 2017 16:33:44 +0100 Subject: [PATCH 52/68] Changed location of linker tables with spillover for extended digi output --- Pr/PrMCTools/src/PrClustersResidual.cpp | 8 ++++++-- Pr/PrMCTools/src/PrClustersResidual.h | 2 ++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Pr/PrMCTools/src/PrClustersResidual.cpp b/Pr/PrMCTools/src/PrClustersResidual.cpp index 520ceab16d..de6a202d10 100644 --- a/Pr/PrMCTools/src/PrClustersResidual.cpp +++ b/Pr/PrMCTools/src/PrClustersResidual.cpp @@ -39,6 +39,10 @@ PrClustersResidual::PrClustersResidual( const std::string& name, m_ftHitManager(nullptr), m_zone(24){ declareProperty("MCHitsLocation",m_mcHitLocation = "/Event/MC/FT/Hits"); + declareProperty("FTClusterToParticleLinkerLocation", + m_ftClusterToParticleLinkerLocation = LHCb::FTLiteClusterLocation::Default + "WithSpillover"); + declareProperty("FTClusterToHitLinkerLocation", + m_ftClusterToHitLinkerLocation = LHCb::FTLiteClusterLocation::Default + "2MCHitsWithSpillover"); declareProperty("HitManagerName",m_hitManagerName = "PrFTHitManager"); declareProperty("DebugTracking",m_debugTracking = false); declareProperty("DoClusterResidual",m_doClusterResidual = false); //Cluster residual tuple @@ -124,8 +128,8 @@ void PrClustersResidual::Occupancy(){ //"/Event/Prev/MC/FT/Hits" LinkedFrom<LHCb::MCHit,LHCb::MCParticle> myMCHitLink( evtSvc(), msgSvc(), LHCb::MCParticleLocation::Default + "2MC" + "FT" + "Hits" ); - LinkedTo<LHCb::MCParticle> myClusterLink ( evtSvc(), msgSvc(), LHCb::FTLiteClusterLocation::Default ); - LinkedTo<LHCb::MCHit> myFTCluster2MCHitLink ( evtSvc(),msgSvc(), LHCb::FTLiteClusterLocation::Default + "2MCHits"); + LinkedTo<LHCb::MCParticle> myClusterLink ( evtSvc(), msgSvc(), m_ftClusterToParticleLinkerLocation ); + LinkedTo<LHCb::MCHit> myFTCluster2MCHitLink ( evtSvc(),msgSvc(), m_ftClusterToHitLinkerLocation); char layerName[100]; char Title[100]; std::vector<int> nHits(12,0); diff --git a/Pr/PrMCTools/src/PrClustersResidual.h b/Pr/PrMCTools/src/PrClustersResidual.h index 0c6c12778d..4ab37712b6 100644 --- a/Pr/PrMCTools/src/PrClustersResidual.h +++ b/Pr/PrMCTools/src/PrClustersResidual.h @@ -104,6 +104,8 @@ private: LHCb::FTLiteCluster getLiteCluster(const LHCb::LHCbID id); std::string m_mcHitLocation; + std::string m_ftClusterToParticleLinkerLocation; + std::string m_ftClusterToHitLinkerLocation; // unsigned int m_zone; bool m_debugTracking; -- GitLab From d8fdd3066a3fb22755856ef960555d31e3bb7ac4 Mon Sep 17 00:00:00 2001 From: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Mon, 6 Mar 2017 18:02:33 +0000 Subject: [PATCH 53/68] Add CPU capabilities selection for Quartic algorithm --- .../CMakeLists.txt | 24 +- .../src/RichQuarticPhotonReco.cpp | 681 +----------------- .../src/RichQuarticPhotonReco.h | 201 +++++- .../src/RichQuarticPhotonReco.icpp | 526 ++++++++++++++ .../src/avx/RichQuarticPhotonReco.cpp | 30 + .../src/avx2/RichQuarticPhotonReco.cpp | 30 + .../src/generic/RichQuarticPhotonReco.cpp | 21 + .../src/sse4/RichQuarticPhotonReco.cpp | 21 + 8 files changed, 846 insertions(+), 688 deletions(-) create mode 100644 Rich/RichFutureRecPhotonAlgorithms/src/RichQuarticPhotonReco.icpp create mode 100644 Rich/RichFutureRecPhotonAlgorithms/src/avx/RichQuarticPhotonReco.cpp create mode 100644 Rich/RichFutureRecPhotonAlgorithms/src/avx2/RichQuarticPhotonReco.cpp create mode 100644 Rich/RichFutureRecPhotonAlgorithms/src/generic/RichQuarticPhotonReco.cpp create mode 100644 Rich/RichFutureRecPhotonAlgorithms/src/sse4/RichQuarticPhotonReco.cpp diff --git a/Rich/RichFutureRecPhotonAlgorithms/CMakeLists.txt b/Rich/RichFutureRecPhotonAlgorithms/CMakeLists.txt index a3c59f6df2..a226a88b4c 100644 --- a/Rich/RichFutureRecPhotonAlgorithms/CMakeLists.txt +++ b/Rich/RichFutureRecPhotonAlgorithms/CMakeLists.txt @@ -5,7 +5,8 @@ gaudi_subdir(RichFutureRecPhotonAlgorithms v1r0) gaudi_depends_on_subdirs(Rich/RichFutureRecBase Rich/RichFutureRecEvent - Rich/RichUtils) + Rich/RichUtils + Kernel/VectorClass) find_package(Boost) find_package(GSL) @@ -16,10 +17,21 @@ find_package(ROOT) include_directories(SYSTEM ${Boost_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS} ${EIGEN_INCLUDE_DIRS}) -# For testing high vectorisation and optimisation levels -#set_property(SOURCE src/RichQuarticPhotonReco.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -O3 -mavx2 -mfma -fabi-version=0 -fabi-compat-version=0 -ffp-contract=fast " ) - gaudi_add_module(RichFutureRecPhotonAlgorithms - src/*.cpp - INCLUDE_DIRS Boost GSL VDT Eigen Rich/RichFutureRecBase Rich/RichFutureRecEvent Rich/RichUtils + src/*.cpp src/generic/*.cpp src/sse4/*.cpp src/avx/*.cpp src/avx2/*.cpp + INCLUDE_DIRS Boost GSL VDT Eigen Kernel/VectorClass Rich/RichFutureRecBase Rich/RichFutureRecEvent Rich/RichUtils LINK_LIBRARIES Boost GSL VDT RichFutureRecBase RichFutureRecEvent RichUtils) + +set_property(SOURCE src/generic/RichQuarticPhotonReco.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-ignored-attributes " ) + +set_property(SOURCE src/sse4/RichQuarticPhotonReco.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-ignored-attributes -O3 -msse4.2 " ) + +set_property(SOURCE src/avx/RichQuarticPhotonReco.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-ignored-attributes -O3 -mavx " ) + +set_property(SOURCE src/avx2/RichQuarticPhotonReco.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-ignored-attributes -O3 -mavx2 -mfma " ) + +if(LCG_COMP STREQUAL "gcc" OR + (BINARY_TAG_COMP_NAME STREQUAL "gcc" AND BINARY_TAG_COMP_VERSION VERSION_LESS "5")) + set_property(SOURCE src/avx/RichQuarticPhotonReco.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -fabi-version=0 " ) + set_property(SOURCE src/avx2/RichQuarticPhotonReco.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -fabi-version=0 " ) +endif() diff --git a/Rich/RichFutureRecPhotonAlgorithms/src/RichQuarticPhotonReco.cpp b/Rich/RichFutureRecPhotonAlgorithms/src/RichQuarticPhotonReco.cpp index 6616869b50..9ca2553298 100644 --- a/Rich/RichFutureRecPhotonAlgorithms/src/RichQuarticPhotonReco.cpp +++ b/Rich/RichFutureRecPhotonAlgorithms/src/RichQuarticPhotonReco.cpp @@ -47,6 +47,15 @@ StatusCode QuarticPhotonReco::initialize() auto sc = MultiTransformer::initialize(); if ( !sc ) return sc; + // Get the CPU capabilities and set dispatch method + //enum CPUID { GENERIC = 0, SSE4 = 6, AVX = 7, AVX2 = 8 }; + //const auto cpuLevel = instrset_detect(); + //_ri_debug << "Instruction set level = " << cpuLevel << endmsg; + //if ( cpuLevel >= AVX2 ) { m_run = &QuarticPhotonReco::run_avx2; } + //else if ( cpuLevel >= AVX ) { m_run = &QuarticPhotonReco::run_avx; } + //else if ( cpuLevel >= SSE4 ) { m_run = &QuarticPhotonReco::run_sse4; } + //else { m_run = &QuarticPhotonReco::run_generic; } + // get the detector elements m_rich[Rich::Rich1] = getDet<DeRich>( DeRichLocations::Rich1 ); m_rich[Rich::Rich2] = getDet<DeRich>( DeRichLocations::Rich2 ); @@ -112,678 +121,6 @@ StatusCode QuarticPhotonReco::initialize() //============================================================================= -OutData -QuarticPhotonReco::operator()( const LHCb::RichTrackSegment::Vector& segments, - const CherenkovAngles::Vector& ckAngles, - const CherenkovResolutions::Vector& ckResolutions, - const SegmentPanelSpacePoints::Vector& trHitPntsLoc, - const SegmentPhotonFlags::Vector& segPhotFlags, - const Rich::PDPixelCluster::Vector& clusters, - const SpacePointVector& globalPoints, - const SpacePointVector& localPoints, - const Relations::TrackToSegments::Vector& tkToSegRels ) const -{ - // use ranges v3 library - using namespace ranges::v3; - - // make the output data - OutData outData; - - // Shortcut to the photons and relations - auto & photons = std::get<0>(outData); - auto & relations = std::get<1>(outData); - // guess at reserve size - const auto resSize = segments.size() * globalPoints.size() / 20; - photons.reserve( resSize ); - relations.reserve( resSize ); - - // View range for pixel data - const auto allPixels = Ranges::ConstZip( clusters, globalPoints, localPoints ); - - // Make 'ranges' for RICH pixels - const auto RPixs = richRanges( allPixels ); - const auto & RichRanges = RPixs[0]; // Complete RICH ranges - const auto & Rich1Ranges = RPixs[1]; // ranges for RICH1 [top,bottom] - const auto & Rich2Ranges = RPixs[2]; // ranges for RICH2 [left,right] - - // local position corrector - // longer term need to remove this - const Rich::Rec::RadPositionCorrector corrector; - - // global photon index - int photonIndex(-1); - - // Loop over the track->segment relations - for ( const auto & inTkRel : tkToSegRels ) - { - // loop over segments for this track - for ( const auto & segIndex : inTkRel.segmentIndices ) - { - // Get the data from the segment containers - const auto & segment = segments[segIndex]; - const auto & tkCkAngles = ckAngles[segIndex]; - const auto & tkCkRes = ckResolutions[segIndex]; - const auto & tkLocPtn = trHitPntsLoc[segIndex]; - const auto & segFlags = segPhotFlags[segIndex]; - - // Is this segment above threshold. Should be implicit due to above segment loop - //if ( ! ( tkCkAngles[lightestActiveHypo()] > 0 ) ) continue; - - // which RICH and radiator - const auto rich = segment.rich(); - const auto rad = segment.radiator(); - - // This implementiation does not support Aerogel - if ( UNLIKELY( Rich::Aerogel == rad ) ) { Exception("Aerogel not supported"); } - - // get the best pixel range for this segment, based on where hits are expected - const auto& pixR = ( segFlags.inBothPanels() ? RichRanges[rich] : - Rich::Rich1 == rich ? - ( segFlags.inPanel(Rich::top) ? - Rich1Ranges[Rich::top] : Rich1Ranges[Rich::bottom] ) : - ( segFlags.inPanel(Rich::left) ? - Rich2Ranges[Rich::left] : Rich2Ranges[Rich::right] ) ); - - // Loop over pixel information - int pixIndex = pixR.first - allPixels.begin() - 1; // (start index - 1) for this range - for ( auto pix_it = pixR.first; pix_it != pixR.second; ++pix_it ) - { - // load the data from the tuple - const auto & cluster = std::get<0>(*pix_it); - const auto & gloPos = std::get<1>(*pix_it); - const auto & locPos = std::get<2>(*pix_it); - // increment the pixel index - ++pixIndex; - - //_ri_verbo << "Trying Segment P=" << segment.bestMomentum() << " Pixel " - // << cluster << endmsg; - - // Apply pre-selection - - // Pixel position, in local HPD coords corrected for average radiator distortion - // Might need to pre-compute and cache this as we repeat it here each segment... - const auto pixP = corrector.correct(locPos,rad); - - // Track local hit point on the same panel as the hit - /// @todo CRJ Need to figure out why I was not correcting this in the current stack... - /// Probably correct but should check. - //const auto segPanelPnt = corrector.correct(tkLocPtn.point(cluster.panel()),rad); - const auto& segPanelPnt = tkLocPtn.point(cluster.panel()); - - // compute the seperation squared - const auto sep2 = ( std::pow( (pixP.x()-segPanelPnt.x()), 2 ) + - std::pow( (pixP.y()-segPanelPnt.y()), 2 ) ); - - // presel. default to rejected - bool SelOK = false; - - // Check overall boundaries - //_ri_verbo << " -> sep2 = " << sep2 << " " << m_maxROI2PreSel[rad] - // << " " << m_minROI2PreSel[rad] << endmsg; - if ( sep2 < m_maxROI2PreSel[rad] && sep2 > m_minROI2PreSel[rad] ) - { - - // estimated CK theta - const auto ckThetaEsti = std::sqrt(sep2)*m_scalePreSel[rad]; - //_ri_verbo << " -> CK theta Esti " << ckThetaEsti << endmsg; - - // Is the hit close to any mass hypo in local coordinate space - SelOK = any_of( activeParticles(), - [sigma=m_nSigmaPreSel[rad],&ckThetaEsti,&tkCkAngles,&tkCkRes] - ( const auto hypo ) - { return fabs(tkCkAngles[hypo]-ckThetaEsti) < sigma*tkCkRes[hypo]; } ); - - } // boundary check - - // Did we pass the pre-sel - if ( !SelOK ) - { - //_ri_verbo << " -> FAILED pre-selection -> reject" << endmsg; - continue; - } - - // Move on to the full Quartic reconstruction - - //std::cout << "Starting photon reco" << std::endl; - - // make a photon object to work on - photons.emplace_back(); - auto & gPhoton = photons.back(); - DataGuard<decltype(photons)> photGuard(photons); - - // pixel side - const auto side = cluster.panel(); - - // Emission point to use for photon reconstruction - // operate directly on photon data member for efficiency - //auto & emissionPoint = gPhoton.emissionPoint(); - //emissionPoint = segment.bestPoint(); - auto emissionPoint = segment.bestPoint(); - - // Photon direction at emission point - // Again, operator directly on data member - //auto & photonDirection = gPhoton.emissionDir(); - Gaudi::XYZVector photonDirection; - - // Final reflection points on sec and spherical mirrors - // operate directly on photon data - //auto & sphReflPoint = gPhoton.sphMirReflectionPoint(); - //auto & secReflPoint = gPhoton.flatMirReflectionPoint(); - Gaudi::XYZPoint sphReflPoint, secReflPoint; - - // fraction of segment path length accessible to the photon - float fraction(1); - - // Pointers to best sec and spherical mirror segments - const DeRichSphMirror * sphSegment = nullptr; - const DeRichSphMirror * secSegment = nullptr; - - // flag to say if this photon candidate is un-ambiguous - default to false - bool unambigPhoton = false; - - // find the reflection of the detection point in the sec mirror - // (virtual detection point) starting with nominal values - // At this we are assuming a flat nominal mirror common to all segments - auto distance = m_rich[rich]->nominalPlane(side).Distance(gloPos); - auto virtDetPoint = gloPos - 2.0 * distance * m_rich[rich]->nominalNormal(side); - - // -------------------------------------------------------------------------------------- - // For gas radiators, try start and end points to see if photon is unambiguous - // NOTE : For this we are using the virtual detection point determined using - // the noimnal flat secondary mirror plane. Now the secondary mirrors are actually - // spherical this may be introducing some additional uncertainties. - // -------------------------------------------------------------------------------------- - if ( m_testForUnambigPhots[rad] ) - { - if ( UNLIKELY( rad == Rich::Aerogel ) ) - { - // use default emission point and assume unambiguous since path length is so short.. - unambigPhoton = true; - } - else // gas radiators - { - - // flag for beam pipe check. Default is OK - bool beamTestOK(true); - - // ------------------------------------------------------------------------------- - // First emission point, at start of track segment - const auto emissionPoint1 = segment.bestPoint(0.01); - // Find mirror segments for this emission point - const DeRichSphMirror* sphSegment1 = nullptr; - const DeRichSphMirror* secSegment1 = nullptr; - Gaudi::XYZPoint sphReflPoint1, secReflPoint1; - if ( !findMirrorData( rich, side, virtDetPoint, emissionPoint1, - sphSegment1, secSegment1, sphReflPoint1, secReflPoint1 ) ) - { - //_ri_debug << rad << " : Failed to reconstruct photon for start of segment" << endmsg; - continue; - } - if ( m_checkBeamPipe[rad] ) - { - beamTestOK = !deBeam(rich)->testForIntersection( emissionPoint1, sphReflPoint1 ); - } - // ------------------------------------------------------------------------------- - - // ------------------------------------------------------------------------------- - // now do it again for emission point #2, at end of segment - const auto emissionPoint2 = segment.bestPoint(0.99); - // Find mirror segments for this emission point - const DeRichSphMirror* sphSegment2 = nullptr; - const DeRichSphMirror* secSegment2 = nullptr; - Gaudi::XYZPoint sphReflPoint2, secReflPoint2; - if ( !findMirrorData( rich, side, virtDetPoint, emissionPoint2, - sphSegment2, secSegment2, sphReflPoint2, secReflPoint2 ) ) - { - //_ri_debug << rad << " : Failed to reconstruct photon for end of segment" << endmsg; - continue; - } - if ( !beamTestOK && m_checkBeamPipe[rad] ) - { - beamTestOK = !deBeam(rich)->testForIntersection( emissionPoint2, sphReflPoint2 ); - } - // ------------------------------------------------------------------------------- - - // ------------------------------------------------------------------------------- - if ( !beamTestOK ) - { - // both start and end points failed beam pipe test -> reject - //_ri_debug << rad << " : Failed ambiguous photon beampipe intersection checks" << endmsg; - continue; - } - // ------------------------------------------------------------------------------- - - // ------------------------------------------------------------------------------- - // Test to see if photon direction hits the real physical mirror segments - // ------------------------------------------------------------------------------- - if ( UNLIKELY(m_checkPrimMirrSegs[rad]) ) - { - // primary mirrors - const auto ok = ( sphSegment1->intersects( emissionPoint1, - sphReflPoint1-emissionPoint1 ) || - sphSegment2->intersects( emissionPoint2, - sphReflPoint2-emissionPoint2 ) ); - if ( !ok ) - { - //_ri_debug << rad << " : Failed mirror segment intersection checks" << endmsg; - continue; - } - } - // ------------------------------------------------------------------------------- - - // ------------------------------------------------------------------------------- - // Get the best gas emission point - if ( !getBestGasEmissionPoint( rad, - sphReflPoint1, - sphReflPoint2, - gloPos, - segment, - emissionPoint, - fraction ) ) - { - //_ri_debug << rad << " : Failed to compute best gas emission point" << endmsg; - continue; - } - // ------------------------------------------------------------------------------- - - // ------------------------------------------------------------------------------- - // Is this an unambiguous photon - I.e. only one possible mirror combination - if ( ( sphSegment1 == sphSegment2 ) && ( secSegment1 == secSegment2 ) ) - { - // Set pointers to the mirror detector objects - sphSegment = sphSegment1; - secSegment = secSegment1; - // rough guesses at reflection points (improved later on) - sphReflPoint = sphReflPoint1 + 0.5*(sphReflPoint2-sphReflPoint1); - secReflPoint = secReflPoint1 + 0.5*(secReflPoint2-secReflPoint1); - // photon is not unambiguous - unambigPhoton = true; - } - // ------------------------------------------------------------------------------- - - } // end radiator type if - - // if configured to do so reject ambiguous photons - if ( UNLIKELY( m_rejectAmbigPhots[rad] && !unambigPhoton ) ) - { - //_ri_debug << rad << " : Failed ambiguous photon test" << endmsg; - continue; - } - - } // end unambiguous photon check - // -------------------------------------------------------------------------------------- - - // -------------------------------------------------------------------------------------- - // Active segment fraction cut - // -------------------------------------------------------------------------------------- - if ( UNLIKELY( fraction < m_minActiveFrac[rad] ) ) - { - //_ri_debug << rad << " : Failed active segment fraction cut" << endmsg; - continue; - } - // -------------------------------------------------------------------------------------- - - // -------------------------------------------------------------------------------------- - // if ambiguous gas photon or if ambiguous photon check above has been skipped, try again - // using best emission point and nominal mirror geometries to get the spherical and sec - // mirrors. Also, force this reconstruction if the above unambiguous test was skipped - // -------------------------------------------------------------------------------------- - if ( UNLIKELY( !m_testForUnambigPhots[rad] || !unambigPhoton ) ) - { - if ( !findMirrorData(rich,side, - virtDetPoint,emissionPoint, - sphSegment,secSegment,sphReflPoint,secReflPoint ) ) - { - //_ri_debug << rad << " : Failed backup photon reconstruction" << endmsg; - continue; - } - } - // -------------------------------------------------------------------------------------- - - // -------------------------------------------------------------------------------------- - // Finally reconstruct the photon using best emission point and the best mirror segments - // -------------------------------------------------------------------------------------- - if ( m_useAlignedMirrSegs[rad] ) - { - - // If iterations are disabled for this radiator, update the virtual detection point - // using the selected mirror segment - if ( UNLIKELY( 0 == m_nMaxQits[rad] ) ) - { - - // Form the virtual detection point - distance = secSegment->centreNormalPlane().Distance(gloPos); - virtDetPoint = gloPos - 2.0 * distance * secSegment->centreNormal(); - - // solve the quartic using the new data - m_quarticSolver.solve<double,2,3>( emissionPoint, - sphSegment->centreOfCurvature(), - virtDetPoint, - sphSegment->radius(), - sphReflPoint ); - - // (re)find the spherical mirror segment - // CRJ - Is this needed ? - sphSegment = m_mirrorSegFinder.get()->findSphMirror( rich, side, sphReflPoint ); - - } - else - { - - // Iterate to final solution, improving the secondary mirror info - int iIt(0); - Gaudi::XYZPoint last_mirror_point(0,0,0); - bool loopOK = true; - while ( iIt < m_nMaxQits[rad] ) - { - - // Get secondary mirror reflection point, - // using the best actual secondary mirror segment at this point - const auto dir = virtDetPoint - sphReflPoint; - const auto sc = ( m_treatSecMirrsFlat[rich] ? - intersectPlane( sphReflPoint, dir, - secSegment->centreNormalPlane(), - secReflPoint ) : - intersectSpherical( sphReflPoint, dir, - secSegment->centreOfCurvature(), - secSegment->radius(), - secReflPoint ) ); - if ( UNLIKELY(!sc) ) - { - //_ri_debug << rad << " : Failed to intersect nominal secondary mirror plane" << endmsg; - loopOK = false; - break; - } - - // (re)find the secondary mirror - secSegment = m_mirrorSegFinder.get()->findSecMirror( rich, side, secReflPoint ); - - // Construct plane tangential to secondary mirror passing through reflection point - const Gaudi::Plane3D plane( secSegment->centreOfCurvature()-secReflPoint, secReflPoint ); - - // re-find the reflection of the detection point in the sec mirror - // (virtual detection point) with this mirror plane - distance = plane.Distance(gloPos); - virtDetPoint = gloPos - 2.0 * distance * plane.Normal(); - - // solve the quartic using the new data - m_quarticSolver.solve<double,2,3>( emissionPoint, - sphSegment->centreOfCurvature(), - virtDetPoint, - sphSegment->radius(), - sphReflPoint ); - - // (re)find the spherical mirror segment - sphSegment = m_mirrorSegFinder.get()->findSphMirror( rich, side, sphReflPoint ); - - // for iterations after the first, see if we are still moving - // If not, abort iterations early - if ( iIt > m_nMinQits[rad] && - (last_mirror_point-secReflPoint).Mag2() < m_minSphMirrTolIt[rad] ) { break; } - - // store last sec mirror point - last_mirror_point = secReflPoint; - - // increment iteration counter - ++iIt; - } - // if above while loop failed, abort this photon - if ( UNLIKELY(!loopOK) ) { continue; } - - } - - } - // -------------------------------------------------------------------------------------- - - // -------------------------------------------------------------------------------------- - // check that spherical mirror reflection point is on the same side as detection point - // and (if configured to do so) photon does not cross between detector sides - // -------------------------------------------------------------------------------------- - if ( UNLIKELY( !sameSide(rad,sphReflPoint,virtDetPoint) ) ) - { - //_ri_debug << rad << " : Reflection point on wrong side" << endmsg; - continue; - } - if ( UNLIKELY( m_checkPhotCrossSides[rad] && - !sameSide(rad,sphReflPoint,emissionPoint) ) ) - { - //_ri_debug << rad << " : Photon crosses between detector sides" << endmsg; - continue; - } - //else { continue; } // uncomment to select ONLY crossing photons - // -------------------------------------------------------------------------------------- - - // -------------------------------------------------------------------------------------- - // For as radiators if ambiguous photon checks are disabled (since this is - // already done for these photons during those checks), check if the photon would have - // intersected with the beampipe - // -------------------------------------------------------------------------------------- - if ( UNLIKELY( m_checkBeamPipe[rad] && !m_testForUnambigPhots[rad] ) ) - { - if ( UNLIKELY( deBeam(rich)->testForIntersection( emissionPoint, sphReflPoint ) ) ) - { - //_ri_debug << rad << " : Failed final beampipe intersection checks" << endmsg; - continue; - } - } - // -------------------------------------------------------------------------------------- - - // -------------------------------------------------------------------------------------- - // If using aligned mirror segments, get the final sec mirror reflection - // point using the best mirror segments available at this point - // For RICH2, use the spherical nature of the scondary mirrors - // For RICH1, where they are much flatter, assume complete flatness - // -------------------------------------------------------------------------------------- - if ( m_useAlignedMirrSegs[rad] ) - { - const auto dir = virtDetPoint - sphReflPoint; - const auto sc = ( m_treatSecMirrsFlat[rich] ? - intersectPlane( sphReflPoint, dir, - secSegment->centreNormalPlane(), - secReflPoint ) : - intersectSpherical( sphReflPoint, dir, - secSegment->centreOfCurvature(), - secSegment->radius(), - secReflPoint ) ); - if ( !sc ) - { - //_ri_debug << rad << " : Failed final secondary mirror plane intersection" << endmsg; - continue; - } - } - // -------------------------------------------------------------------------------------- - - // -------------------------------------------------------------------------------------- - // calculate the cherenkov angles using the photon and track vectors - // -------------------------------------------------------------------------------------- - photonDirection = (sphReflPoint-emissionPoint).Unit(); - float thetaCerenkov(0), phiCerenkov(0); - segment.angleToDirection( photonDirection, thetaCerenkov, phiCerenkov ); - // -------------------------------------------------------------------------------------- - - //--------------------------------------------------------------------------------------- - // Apply fudge factor correction for small biases in CK theta - //--------------------------------------------------------------------------------------- - thetaCerenkov += ckThetaCorrection(rad); - //--------------------------------------------------------------------------------------- - - // -------------------------------------------------------------------------------------- - // Final checks on the Cherenkov angles - // -------------------------------------------------------------------------------------- - if ( UNLIKELY( !checkAngles( rad, tkCkAngles, tkCkRes, - thetaCerenkov, phiCerenkov ) ) ) - { - //_ri_verbo << " -> photon FAILED checkAngleInRange test" << endmsg; - continue; - } - // -------------------------------------------------------------------------------------- - - // -------------------------------------------------------------------------------------- - // Set (remaining) photon parameters - // -------------------------------------------------------------------------------------- - gPhoton.setCherenkovTheta ( thetaCerenkov ); - gPhoton.setCherenkovPhi ( phiCerenkov ); - gPhoton.setActiveSegmentFraction ( fraction ); - //gPhoton.setDetectionPoint ( gloPos ); - gPhoton.setSmartID ( cluster.primaryID() ); - gPhoton.setUnambiguousPhoton ( unambigPhoton ); - //gPhoton.setPrimaryMirror ( sphSegment ); - //gPhoton.setSecondaryMirror ( secSegment ); - //_ri_verbo << "Created photon " << gPhoton << endmsg; - // -------------------------------------------------------------------------------------- - - // If we get here, keep the just made photon - photGuard.setOK(); - // Save relations - relations.emplace_back( ++photonIndex, pixIndex, segIndex, inTkRel.tkIndex ); - //info() << relations.back() << endmsg; - - } - - } - - } - - //_ri_debug << "Created " << photons.size() << " photons" << endmsg; - return outData; -} - -//========================================================================= -// Find mirror segments and reflection points for given data -//========================================================================= -bool -QuarticPhotonReco:: -findMirrorData( const Rich::DetectorType rich, - const Rich::Side side, - const Gaudi::XYZPoint& virtDetPoint, - const Gaudi::XYZPoint& emissionPoint, - const DeRichSphMirror*& sphSegment, - const DeRichSphMirror*& secSegment, - Gaudi::XYZPoint& sphReflPoint, - Gaudi::XYZPoint& secReflPoint ) const -{ - // solve quartic equation with nominal values and find spherical mirror reflection point - m_quarticSolver.solve<double,2,2>( emissionPoint, - m_rich[rich]->nominalCentreOfCurvature(side), - virtDetPoint, - m_rich[rich]->sphMirrorRadius(), - sphReflPoint ); - // find the spherical mirror segment - sphSegment = m_mirrorSegFinder.get()->findSphMirror( rich, side, sphReflPoint ); - // Search for the secondary segment - // Direction vector from primary mirror point to virtual detection point - const auto dir ( virtDetPoint - sphReflPoint ); - // find the sec mirror intersction point and secondary mirror segment - const bool OK = intersectPlane( sphReflPoint, dir, - m_rich[rich]->nominalPlane(side), - secReflPoint ); - if ( OK ) - { - // find the secondary mirror - secSegment = m_mirrorSegFinder.get()->findSecMirror( rich, side, secReflPoint ); - // Re-find the secondary mirror reflection point using the new mirror info - // OK = ( !m_treatSecMirrsFlat[rich] ? - // intersectSpherical( sphReflPoint, dir, - // secSegment->centreOfCurvature(), - // secSegment->radius(), - // secReflPoint ) : - // intersectPlane( sphReflPoint, dir, - // secSegment->centreNormalPlane(), - // secReflPoint ) ); - } - // return - return OK; -} - -//========================================================================= -// Compute the best emission point for the gas radiators using -// the given spherical mirror reflection points -//========================================================================= -bool -QuarticPhotonReco:: -getBestGasEmissionPoint( const Rich::RadiatorType radiator, - const Gaudi::XYZPoint& sphReflPoint1, - const Gaudi::XYZPoint& sphReflPoint2, - const Gaudi::XYZPoint& detectionPoint, - const LHCb::RichTrackSegment & segment, - Gaudi::XYZPoint & emissionPoint, - float & fraction ) const -{ - double alongTkFrac = 0.5; - - if ( radiator == Rich::Rich1Gas ) - { - // First reflection and hit point on same y side ? - const bool sameSide1 = ( sphReflPoint1.y() * detectionPoint.y() > 0 ); - const bool sameSide2 = ( sphReflPoint2.y() * detectionPoint.y() > 0 ); - if ( sameSide1 && sameSide2 ) - { - emissionPoint = segment.bestPoint(); - } - else if ( sameSide1 ) - { - fraction = (float)(std::fabs(sphReflPoint1.y()/(sphReflPoint1.y()-sphReflPoint2.y()))); - alongTkFrac = fraction/2.0; - emissionPoint = segment.bestPoint(alongTkFrac); - } - else if ( sameSide2 ) - { - fraction = (float)(std::fabs(sphReflPoint2.y()/(sphReflPoint1.y()-sphReflPoint2.y()))); - alongTkFrac = 1.0-fraction/2.0; - emissionPoint = segment.bestPoint(alongTkFrac); - } - else - { - //Warning( "Rich1Gas : Both RICH spherical mirror hits opposite side to detection point" ); - return false; - } - - } - else if ( radiator == Rich::Rich2Gas ) - { - // First sphReflPoint and hit point on same x side ? - const bool sameSide1 = ( sphReflPoint1.x() * detectionPoint.x() > 0 ); - const bool sameSide2 = ( sphReflPoint2.x() * detectionPoint.x() > 0 ); - if ( sameSide1 && sameSide2 ) - { - emissionPoint = segment.bestPoint(); - } - else if ( sameSide1 ) - { - fraction = (float)(std::fabs(sphReflPoint1.x()/(sphReflPoint1.x()-sphReflPoint2.x()))); - alongTkFrac = fraction/2.0; - emissionPoint = segment.bestPoint(alongTkFrac); - } - else if ( sameSide2 ) - { - fraction = (float)(std::fabs(sphReflPoint2.x()/(sphReflPoint1.x()-sphReflPoint2.x()))); - alongTkFrac = 1.0-fraction/2.0; - emissionPoint = segment.bestPoint(alongTkFrac); - } - else - { - //Warning( "Rich2Gas : Both RICH spherical mirror hits opposite side to detection point" ); - return false; - } - } - else { Error( "::getBestGasEmissionPoint() called for Aerogel segment !!" ); } - - // if ( msgLevel(MSG::VERBOSE) ) - // { - // verbose() << radiator << " best emission point correction :- " << endmsg - // << " -> Photon detection point = " << detectionPoint << endmsg - // << " -> Sph. Mirror ptns = " << sphReflPoint1 << " " << sphReflPoint2 << endmsg - // << " -> Segment entry/exit = " << trSeg.entryPoint() << " " << trSeg.exitPoint() << endmsg - // << " -> Segment fraction = " << fraction << endmsg - // << " -> Emm. Ptn. Along traj = " << alongTkFrac << endmsg - // << " -> Best Emission point = " << emissionPoint << endmsg; - // } - - return true; -} - -//============================================================================= - // Declaration of the Algorithm Factory DECLARE_ALGORITHM_FACTORY( QuarticPhotonReco ) diff --git a/Rich/RichFutureRecPhotonAlgorithms/src/RichQuarticPhotonReco.h b/Rich/RichFutureRecPhotonAlgorithms/src/RichQuarticPhotonReco.h index 8449cc5409..83b1baead2 100644 --- a/Rich/RichFutureRecPhotonAlgorithms/src/RichQuarticPhotonReco.h +++ b/Rich/RichFutureRecPhotonAlgorithms/src/RichQuarticPhotonReco.h @@ -41,6 +41,9 @@ // interfaces #include "RichInterfaces/IRichMirrorSegFinderLookUpTable.h" +// Vector Class +#include "VectorClass/instrset.h" + namespace Rich { namespace Future @@ -51,6 +54,9 @@ namespace Rich // Use the functional framework using namespace Gaudi::Functional; + // pull in methods from Rich::RayTracingUtils + using namespace Rich::RayTracingUtils; + namespace { /// Shortcut to the output data type @@ -98,8 +104,72 @@ namespace Rich const Rich::PDPixelCluster::Vector& clusters, const SpacePointVector& globalPoints, const SpacePointVector& localPoints, - const Relations::TrackToSegments::Vector& tkToSegRels ) const override; + const Relations::TrackToSegments::Vector& tkToSegRels ) const override + { + return (this->*m_run)( segments, ckAngles, ckResolutions, trHitPntsLoc, + segPhotFlags, clusters, globalPoints, localPoints, tkToSegRels ); + } + private: // dispatch methods + + /** Pointer to dispatch function for the operator call + * Default to lowest common denominator. + * Reset in initialize() according to runtime support */ + OutData (QuarticPhotonReco::*m_run) + ( const LHCb::RichTrackSegment::Vector& segments, + const CherenkovAngles::Vector& ckAngles, + const CherenkovResolutions::Vector& ckResolutions, + const SegmentPanelSpacePoints::Vector& trHitPntsLoc, + const SegmentPhotonFlags::Vector& segPhotFlags, + const Rich::PDPixelCluster::Vector& clusters, + const SpacePointVector& globalPoints, + const SpacePointVector& localPoints, + const Relations::TrackToSegments::Vector& tkToSegRels ) const + = &QuarticPhotonReco::run_generic; + + /// Generic method + OutData run_generic( const LHCb::RichTrackSegment::Vector& segments, + const CherenkovAngles::Vector& ckAngles, + const CherenkovResolutions::Vector& ckResolutions, + const SegmentPanelSpacePoints::Vector& trHitPntsLoc, + const SegmentPhotonFlags::Vector& segPhotFlags, + const Rich::PDPixelCluster::Vector& clusters, + const SpacePointVector& globalPoints, + const SpacePointVector& localPoints, + const Relations::TrackToSegments::Vector& tkToSegRels ) const; + + /// SSE4 method + OutData run_sse4( const LHCb::RichTrackSegment::Vector& segments, + const CherenkovAngles::Vector& ckAngles, + const CherenkovResolutions::Vector& ckResolutions, + const SegmentPanelSpacePoints::Vector& trHitPntsLoc, + const SegmentPhotonFlags::Vector& segPhotFlags, + const Rich::PDPixelCluster::Vector& clusters, + const SpacePointVector& globalPoints, + const SpacePointVector& localPoints, + const Relations::TrackToSegments::Vector& tkToSegRels ) const; + + /// AVX method + OutData run_avx( const LHCb::RichTrackSegment::Vector& segments, + const CherenkovAngles::Vector& ckAngles, + const CherenkovResolutions::Vector& ckResolutions, + const SegmentPanelSpacePoints::Vector& trHitPntsLoc, + const SegmentPhotonFlags::Vector& segPhotFlags, + const Rich::PDPixelCluster::Vector& clusters, + const SpacePointVector& globalPoints, + const SpacePointVector& localPoints, + const Relations::TrackToSegments::Vector& tkToSegRels ) const; + /// AVX2 method + OutData run_avx2( const LHCb::RichTrackSegment::Vector& segments, + const CherenkovAngles::Vector& ckAngles, + const CherenkovResolutions::Vector& ckResolutions, + const SegmentPanelSpacePoints::Vector& trHitPntsLoc, + const SegmentPhotonFlags::Vector& segPhotFlags, + const Rich::PDPixelCluster::Vector& clusters, + const SpacePointVector& globalPoints, + const SpacePointVector& localPoints, + const Relations::TrackToSegments::Vector& tkToSegRels ) const; + private: // methods /// Access the DeRich beam pipe objects @@ -115,15 +185,39 @@ namespace Rich inline float myacos( const float x ) const noexcept { return vdt::fast_acosf(x); } /// Find mirror segments and reflection points for given data - bool findMirrorData( const Rich::DetectorType rich, - const Rich::Side side, - const Gaudi::XYZPoint & virtDetPoint, - const Gaudi::XYZPoint & emissionPoint, - const DeRichSphMirror *& sphSegment, - const DeRichSphMirror *& secSegment, - Gaudi::XYZPoint & sphReflPoint, - Gaudi::XYZPoint & secReflPoint ) const; - + inline bool findMirrorData( const Rich::DetectorType rich, + const Rich::Side side, + const Gaudi::XYZPoint & virtDetPoint, + const Gaudi::XYZPoint & emissionPoint, + const DeRichSphMirror *& sphSegment, + const DeRichSphMirror *& secSegment, + Gaudi::XYZPoint & sphReflPoint, + Gaudi::XYZPoint & secReflPoint ) const + { + // solve quartic equation with nominal values and find spherical mirror reflection point + m_quarticSolver.solve<double,2,2>( emissionPoint, + m_rich[rich]->nominalCentreOfCurvature(side), + virtDetPoint, + m_rich[rich]->sphMirrorRadius(), + sphReflPoint ); + // find the spherical mirror segment + sphSegment = m_mirrorSegFinder.get()->findSphMirror( rich, side, sphReflPoint ); + // Search for the secondary segment + // Direction vector from primary mirror point to virtual detection point + const auto dir ( virtDetPoint - sphReflPoint ); + // find the sec mirror intersction point and secondary mirror segment + const bool OK = intersectPlane( sphReflPoint, dir, + m_rich[rich]->nominalPlane(side), + secReflPoint ); + if ( OK ) + { + // find the secondary mirror + secSegment = m_mirrorSegFinder.get()->findSecMirror( rich, side, secReflPoint ); + } + // return + return OK; + } + /// Compute the best emission point for the gas radiators using /// the given spherical mirror reflection points bool getBestGasEmissionPoint( const Rich::RadiatorType radiator, @@ -226,6 +320,93 @@ namespace Rich }; + //========================================================================= + // Compute the best emission point for the gas radiators using + // the given spherical mirror reflection points + //========================================================================= + inline bool + QuarticPhotonReco:: + getBestGasEmissionPoint( const Rich::RadiatorType radiator, + const Gaudi::XYZPoint& sphReflPoint1, + const Gaudi::XYZPoint& sphReflPoint2, + const Gaudi::XYZPoint& detectionPoint, + const LHCb::RichTrackSegment & segment, + Gaudi::XYZPoint & emissionPoint, + float & fraction ) const + { + double alongTkFrac = 0.5; + + if ( radiator == Rich::Rich1Gas ) + { + // First reflection and hit point on same y side ? + const bool sameSide1 = ( sphReflPoint1.y() * detectionPoint.y() > 0 ); + const bool sameSide2 = ( sphReflPoint2.y() * detectionPoint.y() > 0 ); + if ( sameSide1 && sameSide2 ) + { + emissionPoint = segment.bestPoint(); + } + else if ( sameSide1 ) + { + fraction = (float)(std::fabs(sphReflPoint1.y()/(sphReflPoint1.y()-sphReflPoint2.y()))); + alongTkFrac = fraction/2.0; + emissionPoint = segment.bestPoint(alongTkFrac); + } + else if ( sameSide2 ) + { + fraction = (float)(std::fabs(sphReflPoint2.y()/(sphReflPoint1.y()-sphReflPoint2.y()))); + alongTkFrac = 1.0-fraction/2.0; + emissionPoint = segment.bestPoint(alongTkFrac); + } + else + { + //Warning( "Rich1Gas : Both RICH spherical mirror hits opposite side to detection point" ); + return false; + } + + } + else if ( radiator == Rich::Rich2Gas ) + { + // First sphReflPoint and hit point on same x side ? + const bool sameSide1 = ( sphReflPoint1.x() * detectionPoint.x() > 0 ); + const bool sameSide2 = ( sphReflPoint2.x() * detectionPoint.x() > 0 ); + if ( sameSide1 && sameSide2 ) + { + emissionPoint = segment.bestPoint(); + } + else if ( sameSide1 ) + { + fraction = (float)(std::fabs(sphReflPoint1.x()/(sphReflPoint1.x()-sphReflPoint2.x()))); + alongTkFrac = fraction/2.0; + emissionPoint = segment.bestPoint(alongTkFrac); + } + else if ( sameSide2 ) + { + fraction = (float)(std::fabs(sphReflPoint2.x()/(sphReflPoint1.x()-sphReflPoint2.x()))); + alongTkFrac = 1.0-fraction/2.0; + emissionPoint = segment.bestPoint(alongTkFrac); + } + else + { + //Warning( "Rich2Gas : Both RICH spherical mirror hits opposite side to detection point" ); + return false; + } + } + else { Error( "::getBestGasEmissionPoint() called for Aerogel segment !!" ); } + + // if ( msgLevel(MSG::VERBOSE) ) + // { + // verbose() << radiator << " best emission point correction :- " << endmsg + // << " -> Photon detection point = " << detectionPoint << endmsg + // << " -> Sph. Mirror ptns = " << sphReflPoint1 << " " << sphReflPoint2 << endmsg + // << " -> Segment entry/exit = " << trSeg.entryPoint() << " " << trSeg.exitPoint() << endmsg + // << " -> Segment fraction = " << fraction << endmsg + // << " -> Emm. Ptn. Along traj = " << alongTkFrac << endmsg + // << " -> Best Emission point = " << emissionPoint << endmsg; + // } + + return true; + } + } } } diff --git a/Rich/RichFutureRecPhotonAlgorithms/src/RichQuarticPhotonReco.icpp b/Rich/RichFutureRecPhotonAlgorithms/src/RichQuarticPhotonReco.icpp new file mode 100644 index 0000000000..dd4cb6f94b --- /dev/null +++ b/Rich/RichFutureRecPhotonAlgorithms/src/RichQuarticPhotonReco.icpp @@ -0,0 +1,526 @@ + +{ + // use ranges v3 library + using namespace ranges::v3; + + // make the output data + OutData outData; + + // Shortcut to the photons and relations + auto & photons = std::get<0>(outData); + auto & relations = std::get<1>(outData); + // guess at reserve size + const auto resSize = segments.size() * globalPoints.size() / 20; + photons.reserve( resSize ); + relations.reserve( resSize ); + + // View range for pixel data + const auto allPixels = Ranges::ConstZip( clusters, globalPoints, localPoints ); + + // Make 'ranges' for RICH pixels + const auto RPixs = richRanges( allPixels ); + const auto & RichRanges = RPixs[0]; // Complete RICH ranges + const auto & Rich1Ranges = RPixs[1]; // ranges for RICH1 [top,bottom] + const auto & Rich2Ranges = RPixs[2]; // ranges for RICH2 [left,right] + + // local position corrector + // longer term need to remove this + const Rich::Rec::RadPositionCorrector corrector; + + // global photon index + int photonIndex(-1); + + // Loop over the track->segment relations + for ( const auto & inTkRel : tkToSegRels ) + { + // loop over segments for this track + for ( const auto & segIndex : inTkRel.segmentIndices ) + { + // Get the data from the segment containers + const auto & segment = segments[segIndex]; + const auto & tkCkAngles = ckAngles[segIndex]; + const auto & tkCkRes = ckResolutions[segIndex]; + const auto & tkLocPtn = trHitPntsLoc[segIndex]; + const auto & segFlags = segPhotFlags[segIndex]; + + // Is this segment above threshold. Should be implicit due to above segment loop + //if ( ! ( tkCkAngles[lightestActiveHypo()] > 0 ) ) continue; + + // which RICH and radiator + const auto rich = segment.rich(); + const auto rad = segment.radiator(); + + // This implementiation does not support Aerogel + if ( UNLIKELY( Rich::Aerogel == rad ) ) { Exception("Aerogel not supported"); } + + // get the best pixel range for this segment, based on where hits are expected + const auto& pixR = ( segFlags.inBothPanels() ? RichRanges[rich] : + Rich::Rich1 == rich ? + ( segFlags.inPanel(Rich::top) ? + Rich1Ranges[Rich::top] : Rich1Ranges[Rich::bottom] ) : + ( segFlags.inPanel(Rich::left) ? + Rich2Ranges[Rich::left] : Rich2Ranges[Rich::right] ) ); + + // Loop over pixel information + int pixIndex = pixR.first - allPixels.begin() - 1; // (start index - 1) for this range + for ( auto pix_it = pixR.first; pix_it != pixR.second; ++pix_it ) + { + // load the data from the tuple + const auto & cluster = std::get<0>(*pix_it); + const auto & gloPos = std::get<1>(*pix_it); + const auto & locPos = std::get<2>(*pix_it); + // increment the pixel index + ++pixIndex; + + //_ri_verbo << "Trying Segment P=" << segment.bestMomentum() << " Pixel " + // << cluster << endmsg; + + // Apply pre-selection + + // Pixel position, in local HPD coords corrected for average radiator distortion + // Might need to pre-compute and cache this as we repeat it here each segment... + const auto pixP = corrector.correct(locPos,rad); + + // Track local hit point on the same panel as the hit + /// @todo CRJ Need to figure out why I was not correcting this in the current stack... + /// Probably correct but should check. + //const auto segPanelPnt = corrector.correct(tkLocPtn.point(cluster.panel()),rad); + const auto& segPanelPnt = tkLocPtn.point(cluster.panel()); + + // compute the seperation squared + const auto sep2 = ( std::pow( (pixP.x()-segPanelPnt.x()), 2 ) + + std::pow( (pixP.y()-segPanelPnt.y()), 2 ) ); + + // presel. default to rejected + bool SelOK = false; + + // Check overall boundaries + //_ri_verbo << " -> sep2 = " << sep2 << " " << m_maxROI2PreSel[rad] + // << " " << m_minROI2PreSel[rad] << endmsg; + if ( sep2 < m_maxROI2PreSel[rad] && sep2 > m_minROI2PreSel[rad] ) + { + + // estimated CK theta + const auto ckThetaEsti = std::sqrt(sep2)*m_scalePreSel[rad]; + //_ri_verbo << " -> CK theta Esti " << ckThetaEsti << endmsg; + + // Is the hit close to any mass hypo in local coordinate space + SelOK = any_of( activeParticles(), + [sigma=m_nSigmaPreSel[rad],&ckThetaEsti,&tkCkAngles,&tkCkRes] + ( const auto hypo ) + { return fabs(tkCkAngles[hypo]-ckThetaEsti) < sigma*tkCkRes[hypo]; } ); + + } // boundary check + + // Did we pass the pre-sel + if ( !SelOK ) + { + //_ri_verbo << " -> FAILED pre-selection -> reject" << endmsg; + continue; + } + + // Move on to the full Quartic reconstruction + + //std::cout << "Starting photon reco" << std::endl; + + // make a photon object to work on + photons.emplace_back(); + auto & gPhoton = photons.back(); + DataGuard<decltype(photons)> photGuard(photons); + + // pixel side + const auto side = cluster.panel(); + + // Emission point to use for photon reconstruction + // operate directly on photon data member for efficiency + //auto & emissionPoint = gPhoton.emissionPoint(); + //emissionPoint = segment.bestPoint(); + auto emissionPoint = segment.bestPoint(); + + // Photon direction at emission point + // Again, operator directly on data member + //auto & photonDirection = gPhoton.emissionDir(); + Gaudi::XYZVector photonDirection; + + // Final reflection points on sec and spherical mirrors + // operate directly on photon data + //auto & sphReflPoint = gPhoton.sphMirReflectionPoint(); + //auto & secReflPoint = gPhoton.flatMirReflectionPoint(); + Gaudi::XYZPoint sphReflPoint, secReflPoint; + + // fraction of segment path length accessible to the photon + float fraction(1); + + // Pointers to best sec and spherical mirror segments + const DeRichSphMirror * sphSegment = nullptr; + const DeRichSphMirror * secSegment = nullptr; + + // flag to say if this photon candidate is un-ambiguous - default to false + bool unambigPhoton = false; + + // find the reflection of the detection point in the sec mirror + // (virtual detection point) starting with nominal values + // At this we are assuming a flat nominal mirror common to all segments + auto distance = m_rich[rich]->nominalPlane(side).Distance(gloPos); + auto virtDetPoint = gloPos - 2.0 * distance * m_rich[rich]->nominalNormal(side); + + // -------------------------------------------------------------------------------------- + // For gas radiators, try start and end points to see if photon is unambiguous + // NOTE : For this we are using the virtual detection point determined using + // the noimnal flat secondary mirror plane. Now the secondary mirrors are actually + // spherical this may be introducing some additional uncertainties. + // -------------------------------------------------------------------------------------- + if ( m_testForUnambigPhots[rad] ) + { + if ( UNLIKELY( rad == Rich::Aerogel ) ) + { + // use default emission point and assume unambiguous since path length is so short.. + unambigPhoton = true; + } + else // gas radiators + { + + // flag for beam pipe check. Default is OK + bool beamTestOK(true); + + // ------------------------------------------------------------------------------- + // First emission point, at start of track segment + const auto emissionPoint1 = segment.bestPoint(0.01); + // Find mirror segments for this emission point + const DeRichSphMirror* sphSegment1 = nullptr; + const DeRichSphMirror* secSegment1 = nullptr; + Gaudi::XYZPoint sphReflPoint1, secReflPoint1; + if ( !findMirrorData( rich, side, virtDetPoint, emissionPoint1, + sphSegment1, secSegment1, sphReflPoint1, secReflPoint1 ) ) + { + //_ri_debug << rad << " : Failed to reconstruct photon for start of segment" << endmsg; + continue; + } + if ( m_checkBeamPipe[rad] ) + { + beamTestOK = !deBeam(rich)->testForIntersection( emissionPoint1, sphReflPoint1 ); + } + // ------------------------------------------------------------------------------- + + // ------------------------------------------------------------------------------- + // now do it again for emission point #2, at end of segment + const auto emissionPoint2 = segment.bestPoint(0.99); + // Find mirror segments for this emission point + const DeRichSphMirror* sphSegment2 = nullptr; + const DeRichSphMirror* secSegment2 = nullptr; + Gaudi::XYZPoint sphReflPoint2, secReflPoint2; + if ( !findMirrorData( rich, side, virtDetPoint, emissionPoint2, + sphSegment2, secSegment2, sphReflPoint2, secReflPoint2 ) ) + { + //_ri_debug << rad << " : Failed to reconstruct photon for end of segment" << endmsg; + continue; + } + if ( !beamTestOK && m_checkBeamPipe[rad] ) + { + beamTestOK = !deBeam(rich)->testForIntersection( emissionPoint2, sphReflPoint2 ); + } + // ------------------------------------------------------------------------------- + + // ------------------------------------------------------------------------------- + if ( !beamTestOK ) + { + // both start and end points failed beam pipe test -> reject + //_ri_debug << rad << " : Failed ambiguous photon beampipe intersection checks" << endmsg; + continue; + } + // ------------------------------------------------------------------------------- + + // ------------------------------------------------------------------------------- + // Test to see if photon direction hits the real physical mirror segments + // ------------------------------------------------------------------------------- + if ( UNLIKELY(m_checkPrimMirrSegs[rad]) ) + { + // primary mirrors + const auto ok = ( sphSegment1->intersects( emissionPoint1, + sphReflPoint1-emissionPoint1 ) || + sphSegment2->intersects( emissionPoint2, + sphReflPoint2-emissionPoint2 ) ); + if ( !ok ) + { + //_ri_debug << rad << " : Failed mirror segment intersection checks" << endmsg; + continue; + } + } + // ------------------------------------------------------------------------------- + + // ------------------------------------------------------------------------------- + // Get the best gas emission point + if ( !getBestGasEmissionPoint( rad, + sphReflPoint1, + sphReflPoint2, + gloPos, + segment, + emissionPoint, + fraction ) ) + { + //_ri_debug << rad << " : Failed to compute best gas emission point" << endmsg; + continue; + } + // ------------------------------------------------------------------------------- + + // ------------------------------------------------------------------------------- + // Is this an unambiguous photon - I.e. only one possible mirror combination + if ( ( sphSegment1 == sphSegment2 ) && ( secSegment1 == secSegment2 ) ) + { + // Set pointers to the mirror detector objects + sphSegment = sphSegment1; + secSegment = secSegment1; + // rough guesses at reflection points (improved later on) + sphReflPoint = sphReflPoint1 + 0.5*(sphReflPoint2-sphReflPoint1); + secReflPoint = secReflPoint1 + 0.5*(secReflPoint2-secReflPoint1); + // photon is not unambiguous + unambigPhoton = true; + } + // ------------------------------------------------------------------------------- + + } // end radiator type if + + // if configured to do so reject ambiguous photons + if ( UNLIKELY( m_rejectAmbigPhots[rad] && !unambigPhoton ) ) + { + //_ri_debug << rad << " : Failed ambiguous photon test" << endmsg; + continue; + } + + } // end unambiguous photon check + // -------------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------------- + // Active segment fraction cut + // -------------------------------------------------------------------------------------- + if ( UNLIKELY( fraction < m_minActiveFrac[rad] ) ) + { + //_ri_debug << rad << " : Failed active segment fraction cut" << endmsg; + continue; + } + // -------------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------------- + // if ambiguous gas photon or if ambiguous photon check above has been skipped, try again + // using best emission point and nominal mirror geometries to get the spherical and sec + // mirrors. Also, force this reconstruction if the above unambiguous test was skipped + // -------------------------------------------------------------------------------------- + if ( UNLIKELY( !m_testForUnambigPhots[rad] || !unambigPhoton ) ) + { + if ( !findMirrorData(rich,side, + virtDetPoint,emissionPoint, + sphSegment,secSegment,sphReflPoint,secReflPoint ) ) + { + //_ri_debug << rad << " : Failed backup photon reconstruction" << endmsg; + continue; + } + } + // -------------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------------- + // Finally reconstruct the photon using best emission point and the best mirror segments + // -------------------------------------------------------------------------------------- + if ( m_useAlignedMirrSegs[rad] ) + { + + // If iterations are disabled for this radiator, update the virtual detection point + // using the selected mirror segment + if ( UNLIKELY( 0 == m_nMaxQits[rad] ) ) + { + + // Form the virtual detection point + distance = secSegment->centreNormalPlane().Distance(gloPos); + virtDetPoint = gloPos - 2.0 * distance * secSegment->centreNormal(); + + // solve the quartic using the new data + m_quarticSolver.solve<double,2,3>( emissionPoint, + sphSegment->centreOfCurvature(), + virtDetPoint, + sphSegment->radius(), + sphReflPoint ); + + // (re)find the spherical mirror segment + // CRJ - Is this needed ? + sphSegment = m_mirrorSegFinder.get()->findSphMirror( rich, side, sphReflPoint ); + + } + else + { + + // Iterate to final solution, improving the secondary mirror info + int iIt(0); + Gaudi::XYZPoint last_mirror_point(0,0,0); + bool loopOK = true; + while ( iIt < m_nMaxQits[rad] ) + { + + // Get secondary mirror reflection point, + // using the best actual secondary mirror segment at this point + const auto dir = virtDetPoint - sphReflPoint; + const auto sc = ( m_treatSecMirrsFlat[rich] ? + intersectPlane( sphReflPoint, dir, + secSegment->centreNormalPlane(), + secReflPoint ) : + intersectSpherical( sphReflPoint, dir, + secSegment->centreOfCurvature(), + secSegment->radius(), + secReflPoint ) ); + if ( UNLIKELY(!sc) ) + { + //_ri_debug << rad << " : Failed to intersect nominal secondary mirror plane" << endmsg; + loopOK = false; + break; + } + + // (re)find the secondary mirror + secSegment = m_mirrorSegFinder.get()->findSecMirror( rich, side, secReflPoint ); + + // Construct plane tangential to secondary mirror passing through reflection point + const Gaudi::Plane3D plane( secSegment->centreOfCurvature()-secReflPoint, secReflPoint ); + + // re-find the reflection of the detection point in the sec mirror + // (virtual detection point) with this mirror plane + distance = plane.Distance(gloPos); + virtDetPoint = gloPos - 2.0 * distance * plane.Normal(); + + // solve the quartic using the new data + m_quarticSolver.solve<double,2,3>( emissionPoint, + sphSegment->centreOfCurvature(), + virtDetPoint, + sphSegment->radius(), + sphReflPoint ); + + // (re)find the spherical mirror segment + sphSegment = m_mirrorSegFinder.get()->findSphMirror( rich, side, sphReflPoint ); + + // for iterations after the first, see if we are still moving + // If not, abort iterations early + if ( iIt > m_nMinQits[rad] && + (last_mirror_point-secReflPoint).Mag2() < m_minSphMirrTolIt[rad] ) { break; } + + // store last sec mirror point + last_mirror_point = secReflPoint; + + // increment iteration counter + ++iIt; + } + // if above while loop failed, abort this photon + if ( UNLIKELY(!loopOK) ) { continue; } + + } + + } + // -------------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------------- + // check that spherical mirror reflection point is on the same side as detection point + // and (if configured to do so) photon does not cross between detector sides + // -------------------------------------------------------------------------------------- + if ( UNLIKELY( !sameSide(rad,sphReflPoint,virtDetPoint) ) ) + { + //_ri_debug << rad << " : Reflection point on wrong side" << endmsg; + continue; + } + if ( UNLIKELY( m_checkPhotCrossSides[rad] && + !sameSide(rad,sphReflPoint,emissionPoint) ) ) + { + //_ri_debug << rad << " : Photon crosses between detector sides" << endmsg; + continue; + } + //else { continue; } // uncomment to select ONLY crossing photons + // -------------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------------- + // For as radiators if ambiguous photon checks are disabled (since this is + // already done for these photons during those checks), check if the photon would have + // intersected with the beampipe + // -------------------------------------------------------------------------------------- + if ( UNLIKELY( m_checkBeamPipe[rad] && !m_testForUnambigPhots[rad] ) ) + { + if ( UNLIKELY( deBeam(rich)->testForIntersection( emissionPoint, sphReflPoint ) ) ) + { + //_ri_debug << rad << " : Failed final beampipe intersection checks" << endmsg; + continue; + } + } + // -------------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------------- + // If using aligned mirror segments, get the final sec mirror reflection + // point using the best mirror segments available at this point + // For RICH2, use the spherical nature of the scondary mirrors + // For RICH1, where they are much flatter, assume complete flatness + // -------------------------------------------------------------------------------------- + if ( m_useAlignedMirrSegs[rad] ) + { + const auto dir = virtDetPoint - sphReflPoint; + const auto sc = ( m_treatSecMirrsFlat[rich] ? + intersectPlane( sphReflPoint, dir, + secSegment->centreNormalPlane(), + secReflPoint ) : + intersectSpherical( sphReflPoint, dir, + secSegment->centreOfCurvature(), + secSegment->radius(), + secReflPoint ) ); + if ( !sc ) + { + //_ri_debug << rad << " : Failed final secondary mirror plane intersection" << endmsg; + continue; + } + } + // -------------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------------- + // calculate the cherenkov angles using the photon and track vectors + // -------------------------------------------------------------------------------------- + photonDirection = (sphReflPoint-emissionPoint).Unit(); + float thetaCerenkov(0), phiCerenkov(0); + segment.angleToDirection( photonDirection, thetaCerenkov, phiCerenkov ); + // -------------------------------------------------------------------------------------- + + //--------------------------------------------------------------------------------------- + // Apply fudge factor correction for small biases in CK theta + //--------------------------------------------------------------------------------------- + thetaCerenkov += ckThetaCorrection(rad); + //--------------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------------- + // Final checks on the Cherenkov angles + // -------------------------------------------------------------------------------------- + if ( UNLIKELY( !checkAngles( rad, tkCkAngles, tkCkRes, + thetaCerenkov, phiCerenkov ) ) ) + { + //_ri_verbo << " -> photon FAILED checkAngleInRange test" << endmsg; + continue; + } + // -------------------------------------------------------------------------------------- + + // -------------------------------------------------------------------------------------- + // Set (remaining) photon parameters + // -------------------------------------------------------------------------------------- + gPhoton.setCherenkovTheta ( thetaCerenkov ); + gPhoton.setCherenkovPhi ( phiCerenkov ); + gPhoton.setActiveSegmentFraction ( fraction ); + //gPhoton.setDetectionPoint ( gloPos ); + gPhoton.setSmartID ( cluster.primaryID() ); + gPhoton.setUnambiguousPhoton ( unambigPhoton ); + //gPhoton.setPrimaryMirror ( sphSegment ); + //gPhoton.setSecondaryMirror ( secSegment ); + //_ri_verbo << "Created photon " << gPhoton << endmsg; + // -------------------------------------------------------------------------------------- + + // If we get here, keep the just made photon + photGuard.setOK(); + // Save relations + relations.emplace_back( ++photonIndex, pixIndex, segIndex, inTkRel.tkIndex ); + //info() << relations.back() << endmsg; + + } + + } + + } + + //_ri_debug << "Created " << photons.size() << " photons" << endmsg; + return outData; +} diff --git a/Rich/RichFutureRecPhotonAlgorithms/src/avx/RichQuarticPhotonReco.cpp b/Rich/RichFutureRecPhotonAlgorithms/src/avx/RichQuarticPhotonReco.cpp new file mode 100644 index 0000000000..1840557ea2 --- /dev/null +++ b/Rich/RichFutureRecPhotonAlgorithms/src/avx/RichQuarticPhotonReco.cpp @@ -0,0 +1,30 @@ + +// local +#include "../RichQuarticPhotonReco.h" + +// All code is in general Rich reconstruction namespace +using namespace Rich::Future; +using namespace Rich::Future::Rec; + +struct avx_guard { + // see Agner Fog's optimization guide, 12.1 about mixing AVX and non-AVX code, + // (http://www.agner.org/optimize/optimizing_cpp.pdf) + // and preserving the YMM register state. + // Invoking __mm256_zeroupper seems to reduce the overhead when switching. + ~avx_guard() { _mm256_zeroupper(); } +}; + +OutData +QuarticPhotonReco::run_avx( const LHCb::RichTrackSegment::Vector& segments, + const CherenkovAngles::Vector& ckAngles, + const CherenkovResolutions::Vector& ckResolutions, + const SegmentPanelSpacePoints::Vector& trHitPntsLoc, + const SegmentPhotonFlags::Vector& segPhotFlags, + const Rich::PDPixelCluster::Vector& clusters, + const SpacePointVector& globalPoints, + const SpacePointVector& localPoints, + const Relations::TrackToSegments::Vector& tkToSegRels ) const +{ + avx_guard guard{}; +#include "../RichQuarticPhotonReco.icpp" +} diff --git a/Rich/RichFutureRecPhotonAlgorithms/src/avx2/RichQuarticPhotonReco.cpp b/Rich/RichFutureRecPhotonAlgorithms/src/avx2/RichQuarticPhotonReco.cpp new file mode 100644 index 0000000000..672aa63991 --- /dev/null +++ b/Rich/RichFutureRecPhotonAlgorithms/src/avx2/RichQuarticPhotonReco.cpp @@ -0,0 +1,30 @@ + +// local +#include "../RichQuarticPhotonReco.h" + +// All code is in general Rich reconstruction namespace +using namespace Rich::Future; +using namespace Rich::Future::Rec; + +struct avx_guard { + // see Agner Fog's optimization guide, 12.1 about mixing AVX and non-AVX code, + // (http://www.agner.org/optimize/optimizing_cpp.pdf) + // and preserving the YMM register state. + // Invoking __mm256_zeroupper seems to reduce the overhead when switching. + ~avx_guard() { _mm256_zeroupper(); } +}; + +OutData +QuarticPhotonReco::run_avx2( const LHCb::RichTrackSegment::Vector& segments, + const CherenkovAngles::Vector& ckAngles, + const CherenkovResolutions::Vector& ckResolutions, + const SegmentPanelSpacePoints::Vector& trHitPntsLoc, + const SegmentPhotonFlags::Vector& segPhotFlags, + const Rich::PDPixelCluster::Vector& clusters, + const SpacePointVector& globalPoints, + const SpacePointVector& localPoints, + const Relations::TrackToSegments::Vector& tkToSegRels ) const +{ + avx_guard guard{}; +#include "../RichQuarticPhotonReco.icpp" +} diff --git a/Rich/RichFutureRecPhotonAlgorithms/src/generic/RichQuarticPhotonReco.cpp b/Rich/RichFutureRecPhotonAlgorithms/src/generic/RichQuarticPhotonReco.cpp new file mode 100644 index 0000000000..d5db58c914 --- /dev/null +++ b/Rich/RichFutureRecPhotonAlgorithms/src/generic/RichQuarticPhotonReco.cpp @@ -0,0 +1,21 @@ + +// local +#include "../RichQuarticPhotonReco.h" + +// All code is in general Rich reconstruction namespace +using namespace Rich::Future; +using namespace Rich::Future::Rec; + +OutData +QuarticPhotonReco::run_generic( const LHCb::RichTrackSegment::Vector& segments, + const CherenkovAngles::Vector& ckAngles, + const CherenkovResolutions::Vector& ckResolutions, + const SegmentPanelSpacePoints::Vector& trHitPntsLoc, + const SegmentPhotonFlags::Vector& segPhotFlags, + const Rich::PDPixelCluster::Vector& clusters, + const SpacePointVector& globalPoints, + const SpacePointVector& localPoints, + const Relations::TrackToSegments::Vector& tkToSegRels ) const +{ +#include "../RichQuarticPhotonReco.icpp" +} diff --git a/Rich/RichFutureRecPhotonAlgorithms/src/sse4/RichQuarticPhotonReco.cpp b/Rich/RichFutureRecPhotonAlgorithms/src/sse4/RichQuarticPhotonReco.cpp new file mode 100644 index 0000000000..82131fc133 --- /dev/null +++ b/Rich/RichFutureRecPhotonAlgorithms/src/sse4/RichQuarticPhotonReco.cpp @@ -0,0 +1,21 @@ + +// local +#include "../RichQuarticPhotonReco.h" + +// All code is in general Rich reconstruction namespace +using namespace Rich::Future; +using namespace Rich::Future::Rec; + +OutData +QuarticPhotonReco::run_sse4( const LHCb::RichTrackSegment::Vector& segments, + const CherenkovAngles::Vector& ckAngles, + const CherenkovResolutions::Vector& ckResolutions, + const SegmentPanelSpacePoints::Vector& trHitPntsLoc, + const SegmentPhotonFlags::Vector& segPhotFlags, + const Rich::PDPixelCluster::Vector& clusters, + const SpacePointVector& globalPoints, + const SpacePointVector& localPoints, + const Relations::TrackToSegments::Vector& tkToSegRels ) const +{ +#include "../RichQuarticPhotonReco.icpp" +} -- GitLab From 2e830441ceb22af09b91747e484e5fb5c621ffde Mon Sep 17 00:00:00 2001 From: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Mon, 6 Mar 2017 18:02:57 +0000 Subject: [PATCH 54/68] Update test package build options --- Rich/RichRecTests/CMakeLists.txt | 32 +++++++++++++++------- Rich/RichRecTests/src/RayTracing/main.icpp | 10 +++---- 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/Rich/RichRecTests/CMakeLists.txt b/Rich/RichRecTests/CMakeLists.txt index a227c20223..8ac0bf8ba3 100644 --- a/Rich/RichRecTests/CMakeLists.txt +++ b/Rich/RichRecTests/CMakeLists.txt @@ -20,9 +20,9 @@ find_package(Vc) find_package(ROOT COMPONENTS MathCore GenVector ) message(STATUS "Using Vc ${Vc_INCLUDE_DIR} ${Vc_LIB_DIR}") -message(STATUS "Vc DEFINITIONS ${Vc_DEFINITIONS}") -message(STATUS "Vc COMPILE flags ${Vc_COMPILE_FLAGS}") -message(STATUS "Vc ARCHITECTURE flags ${Vc_ARCHITECTURE_FLAGS}") +#message(STATUS "Vc DEFINITIONS ${Vc_DEFINITIONS}") +#message(STATUS "Vc COMPILE flags ${Vc_COMPILE_FLAGS}") +#message(STATUS "Vc ARCHITECTURE flags ${Vc_ARCHITECTURE_FLAGS}") include_directories(SYSTEM ${Boost_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS} ${EIGEN_INCLUDE_DIRS} ${Vc_INCLUDE_DIR}) @@ -34,28 +34,28 @@ if(GAUDI_BUILD_TESTS) INCLUDE_DIRS Kernel/TemplatedGenVector ROOT Vc Eigen GSL VectorClass src LINK_LIBRARIES LHCbMathLib GSL GaudiKernel TemplatedGenVectorLib ) target_link_libraries( RichPhotonRecoTestSSE4 -lrt ) - set_property(SOURCE src/RayTracing/main_sse4.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -msse4.2 " ) + set_property(SOURCE src/PhotonReco/main_sse4.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -msse4.2 " ) gaudi_add_executable(RichPhotonRecoTestAVX src/PhotonReco/main_avx.cpp INCLUDE_DIRS Kernel/TemplatedGenVector ROOT Vc Eigen GSL VectorClass src LINK_LIBRARIES LHCbMathLib GSL GaudiKernel TemplatedGenVectorLib ) target_link_libraries( RichPhotonRecoTestAVX -lrt ) - set_property(SOURCE src/RayTracing/main_avx.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -mavx -fabi-version=0 -fabi-compat-version=0 -ffp-contract=fast " ) + set_property(SOURCE src/PhotonReco/main_avx.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -mavx " ) gaudi_add_executable(RichPhotonRecoTestAVX2 src/PhotonReco/main_avx2.cpp INCLUDE_DIRS Kernel/TemplatedGenVector ROOT Vc Eigen GSL VectorClass src LINK_LIBRARIES LHCbMathLib GSL GaudiKernel TemplatedGenVectorLib ) target_link_libraries( RichPhotonRecoTestAVX2 -lrt ) - set_property(SOURCE src/RayTracing/main_avx2.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -mavx2 -fabi-version=0 -fabi-compat-version=0 -ffp-contract=fast " ) + set_property(SOURCE src/PhotonReco/main_avx2.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -mavx2 " ) gaudi_add_executable(RichPhotonRecoTestAVX2FMA src/PhotonReco/main_avx2fma.cpp INCLUDE_DIRS Kernel/TemplatedGenVector ROOT Vc Eigen GSL VectorClass src LINK_LIBRARIES LHCbMathLib GSL GaudiKernel TemplatedGenVectorLib ) target_link_libraries( RichPhotonRecoTestAVX2FMA -lrt ) - set_property(SOURCE src/RayTracing/main_avx2fma.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -mfma -mavx2 -fabi-version=0 -fabi-compat-version=0 -ffp-contract=fast " ) + set_property(SOURCE src/PhotonReco/main_avx2fma.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -mfma -mavx2 " ) @@ -71,20 +71,32 @@ if(GAUDI_BUILD_TESTS) INCLUDE_DIRS Kernel/TemplatedGenVector ROOT Vc Eigen GSL VectorClass src LINK_LIBRARIES LHCbMathLib GSL GaudiKernel TemplatedGenVectorLib ) target_link_libraries( RichRayTracingTestAVX "-lrt ${Vc_LIB_DIR}/libVc.a" ) - set_property(SOURCE src/RayTracing/main_avx.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-ignored-attributes -mavx -fabi-version=0 -fabi-compat-version=0 -ffp-contract=fast " ) + set_property(SOURCE src/RayTracing/main_avx.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-ignored-attributes -mavx " ) gaudi_add_executable(RichRayTracingTestAVX2 src/RayTracing/main_avx2.cpp INCLUDE_DIRS Kernel/TemplatedGenVector ROOT Vc Eigen GSL VectorClass src LINK_LIBRARIES LHCbMathLib GSL GaudiKernel TemplatedGenVectorLib ) target_link_libraries( RichRayTracingTestAVX2 "-lrt ${Vc_LIB_DIR}/libVc.a" ) - set_property(SOURCE src/RayTracing/main_avx2.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-ignored-attributes -mavx2 -fabi-version=0 -fabi-compat-version=0 -ffp-contract=fast " ) + set_property(SOURCE src/RayTracing/main_avx2.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-ignored-attributes -mavx2 " ) gaudi_add_executable(RichRayTracingTestAVX2FMA src/RayTracing/main_avx2fma.cpp INCLUDE_DIRS Kernel/TemplatedGenVector ROOT Vc Eigen GSL VectorClass src LINK_LIBRARIES LHCbMathLib GSL GaudiKernel TemplatedGenVectorLib ) target_link_libraries( RichRayTracingTestAVX2FMA "-lrt ${Vc_LIB_DIR}/libVc.a" ) - set_property(SOURCE src/RayTracing/main_avx2fma.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-ignored-attributes -mfma -mavx2 -fabi-version=0 -fabi-compat-version=0 -ffp-contract=fast " ) + set_property(SOURCE src/RayTracing/main_avx2fma.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-ignored-attributes -mfma -mavx2 " ) + + + if(LCG_COMP STREQUAL "gcc" OR + (BINARY_TAG_COMP_NAME STREQUAL "gcc" AND BINARY_TAG_COMP_VERSION VERSION_LESS "5")) + set_property(SOURCE src/PhotonReco/main_avx.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -fabi-version=0 " ) + set_property(SOURCE src/PhotonReco/main_avx2.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -fabi-version=0 " ) + set_property(SOURCE src/PhotonReco/main_avx2fma.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -fabi-version=0 " ) + set_property(SOURCE src/RayTracing/main_avx.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -fabi-version=0 " ) + set_property(SOURCE src/RayTracing/main_avx2.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -fabi-version=0 " ) + set_property(SOURCE src/RayTracing/main_avx2fma.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -fabi-version=0 " ) + endif() + endif() diff --git a/Rich/RichRecTests/src/RayTracing/main.icpp b/Rich/RichRecTests/src/RayTracing/main.icpp index 802a83b2b7..8fb4bbf692 100644 --- a/Rich/RichRecTests/src/RayTracing/main.icpp +++ b/Rich/RichRecTests/src/RayTracing/main.icpp @@ -77,7 +77,7 @@ inline void trace( DATA & dataV ) { reflectSpherical( data.position, data.direction, data.CoC, data.radius ); reflectPlane ( data.position, data.direction, data.plane ); - std::cout << data.position << std::endl; + //std::cout << data.position << std::endl; } } @@ -89,8 +89,8 @@ unsigned long long int __attribute__((noinline)) rayTrace( const DATA & in_dataV unsigned long long int best_dur{ 99999999999999999 }; - const unsigned int nTests = 1; - std::cout << "Running " << nTests << " tests on " << in_dataV.size() << " data objects" << std::endl; + const unsigned int nTests = 10000; + //std::cout << "Running " << nTests << " tests on " << in_dataV.size() << " data objects" << std::endl; DATA dataV; // working data copy; for ( unsigned int i = 0; i < nTests; ++i ) { @@ -108,8 +108,8 @@ unsigned long long int __attribute__((noinline)) rayTrace( const DATA & in_dataV int main ( int /*argc*/, char** /*argv*/ ) { - //const unsigned int nPhotons = 96 * 1e2; - const unsigned int nPhotons = 8; + const unsigned int nPhotons = 96 * 1e2; + //const unsigned int nPhotons = 8; std::cout << "Creating " << nPhotons << " random photons ..." << std::endl; // Templated GenVector -- GitLab From 67bbd664526adce3f83fdd9a0e737f084abf82a6 Mon Sep 17 00:00:00 2001 From: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Mon, 6 Mar 2017 18:03:22 +0000 Subject: [PATCH 55/68] Add missing array include to QuarticSolverNewton.h --- Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h b/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h index 097bfeec93..8a83c1c857 100755 --- a/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h +++ b/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h @@ -18,6 +18,7 @@ // STL #include <math.h> #include <type_traits> +#include <array> // VDT #include "vdt/asin.h" -- GitLab From cbac48207bc08477b481314a59afa712c9d10965 Mon Sep 17 00:00:00 2001 From: Renato <rquaglia@lxplus.cern.ch> Date: Mon, 6 Mar 2017 19:42:57 +0100 Subject: [PATCH 56/68] update Cluster Residual tool using new v61 convention and adding entry/exit point position of MCHit in ntuples --- Pr/PrMCTools/CMakeLists.txt | 5 +- Pr/PrMCTools/src/PrClustersResidual.cpp | 121 ++++++++++++++++++------ Pr/PrMCTools/src/PrClustersResidual.h | 41 +++----- 3 files changed, 112 insertions(+), 55 deletions(-) diff --git a/Pr/PrMCTools/CMakeLists.txt b/Pr/PrMCTools/CMakeLists.txt index 82046778da..a682e63eee 100644 --- a/Pr/PrMCTools/CMakeLists.txt +++ b/Pr/PrMCTools/CMakeLists.txt @@ -3,7 +3,8 @@ ################################################################################ gaudi_subdir(PrMCTools v2r12) -gaudi_depends_on_subdirs(Det/VPDet +gaudi_depends_on_subdirs(Det/FTDet + Det/VPDet Det/STDet Event/FTEvent Event/LinkerEvent @@ -19,5 +20,5 @@ include_directories(SYSTEM ${Boost_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS}) gaudi_add_module(PrMCTools src/*.cpp INCLUDE_DIRS Event/FTEvent Pr/PrPixel - LINK_LIBRARIES LinkerEvent MCEvent GaudiAlgLib PrKernel VPDetLib STDetLib LoKiMCLib) + LINK_LIBRARIES LinkerEvent MCEvent GaudiAlgLib PrKernel VPDetLib STDetLib FTDetLib LoKiMCLib) diff --git a/Pr/PrMCTools/src/PrClustersResidual.cpp b/Pr/PrMCTools/src/PrClustersResidual.cpp index de6a202d10..a1b5fc54bc 100644 --- a/Pr/PrMCTools/src/PrClustersResidual.cpp +++ b/Pr/PrMCTools/src/PrClustersResidual.cpp @@ -38,20 +38,6 @@ PrClustersResidual::PrClustersResidual( const std::string& name, : GaudiTupleAlg ( name , pSvcLocator ), m_ftHitManager(nullptr), m_zone(24){ - declareProperty("MCHitsLocation",m_mcHitLocation = "/Event/MC/FT/Hits"); - declareProperty("FTClusterToParticleLinkerLocation", - m_ftClusterToParticleLinkerLocation = LHCb::FTLiteClusterLocation::Default + "WithSpillover"); - declareProperty("FTClusterToHitLinkerLocation", - m_ftClusterToHitLinkerLocation = LHCb::FTLiteClusterLocation::Default + "2MCHitsWithSpillover"); - declareProperty("HitManagerName",m_hitManagerName = "PrFTHitManager"); - declareProperty("DebugTracking",m_debugTracking = false); - declareProperty("DoClusterResidual",m_doClusterResidual = false); //Cluster residual tuple - declareProperty("DoTrackStudy",m_doTrackStudy = false); // Produce tuple for track studies - declareProperty("DecodeData",m_decodeData = false); //ask to decode data ( is False if other algorithms are runned - declareProperty("OnlyHasT",m_onlyHasT=false); //(keep only MCParticles with hasT = true - declareProperty("RemoveClones",m_removeClones = true); //Observed clones MCHits when processed ( not understood ) - declareProperty("DumpAllHits",m_dumpAllHits = false); - declareProperty("Occupancy",m_Occupancy = true); } //============================================================================= // Destructor @@ -87,8 +73,17 @@ StatusCode PrClustersResidual::initialize() { //============================================================================= // Main execution //============================================================================= -StatusCode PrClustersResidual::execute() { - +StatusCode PrClustersResidual::execute() { + m_ftDet = getDet<DeFTDetector>(DeFTDetectorLocation::Default); + if( UNLIKELY( !m_ftDet) ){ + error() << " Cannot load the FTDetector from default location" << endmsg; + return StatusCode::FAILURE; + }else if( m_ftDet->version() < 61){ + error()<< "This code requires FTDet v6.1 or higher "<<endmsg; + return StatusCode::FAILURE; + } + + if ( msgLevel(MSG::DEBUG) ) debug() << "==> Execute" << endmsg; m_nEvents++; if(m_doClusterResidual){ @@ -153,7 +148,7 @@ void PrClustersResidual::Occupancy(){ int recoblewanted = 0; LHCb::MCParticles* mcParts = getIfExists<LHCb::MCParticles> ( LHCb::MCParticleLocation::Default ); LHCb::MCParticle* mcPart = nullptr; - for( LHCb::MCParticles::const_iterator iPart = mcParts->begin(); iPart != mcParts->end(); ++iPart){ + for( auto iPart = mcParts->begin(); iPart != mcParts->end(); ++iPart){ mcPart = (*iPart); bool isRecoble = trackInfo.hasT(mcPart); bool recobleWanted = isRecoble && (mcPart->originVertex()->isPrimary() || mcPart->originVertex()->isDecay()); @@ -178,8 +173,30 @@ void PrClustersResidual::Occupancy(){ for(auto itH = m_ftHitManager->getIterator_Begin(zoneI); m_ftHitManager->getIterator_End(zoneI) != itH;++itH){ hit = &(*itH); nHits[layer]++; - LHCb::FTLiteCluster liteCluster = getLiteCluster(hit->id()); - int index = liteCluster.channelID().uniqueSiPM() & 511; + auto liteCluster = getLiteCluster(hit->id()); + + //---- new numbering scheme (v61 sci-fi) plots for occupancy! pseudochannel conversion needed! + /* + It requires to have the m_ftDet as private member of the algorithm and also modify the CMakeLists to compile + PrMCTools linking the Det/FTDet package. + */ + int quarter = liteCluster.channelID().quarter(); + const auto chanID = liteCluster.channelID(); + const DeFTModule* module = m_ftDet->findModule( chanID ); + if( module == nullptr){ + error()<<"Cannot find Module associated to FTChannelID : "<<chanID<<endmsg; + error()<<"Abort Occupancy plot checking"<<endmsg; + return; + } + int pseudochannel = module->pseudoChannel( chanID ); + //--- runs from [0 to 12,287] (96 SiPm *128 channels/SiPm) + //--- 4 quartes [0,1,2,3] , 128 channels squeezed to 1 value. (Occupancy in terms of Hits/SiPM array [128 channels] + //--- ToDo : make it depenent on xml geometry information through m_ftDet + int sipm = std::floor( pseudochannel/128); + int index = quarter * 128 + sipm ; + // old way [ < v61 ] : int index = liteCluster.channelID().uniqueSiPM() & 511; + + sprintf(layerName,"Layer%i/AllContributions",layer); sprintf(Title,"Sipm Index Layer %i;SiPm Id;Clusters/Sipm/Event",layer); plot1D(index,layerName,Title,-0.5,511.5,512); @@ -423,6 +440,8 @@ void PrClustersResidual::TrackStudy(){ debug()<<"For the processed MCParticle i found "<<track.size()<<"PrHits associated to "<<assoc_MCHit.size()<<" MCHits"<<endmsg; tuple->farray("FiredLayers_Counter",firedLayers,"FiredLayers",24); tuple->column("CheatedSeeding_NHits",totHits); + std::vector<double> MCHit_EntryX,MCHit_EntryY,MCHit_EntryZ; + std::vector<double> MCHit_ExitX,MCHit_ExitY,MCHit_ExitZ; std::vector<double> MCHit_X,MCHit_Y,MCHit_Z; std::vector<double> MCHit_tx,MCHit_ty,MCHit_p; std::vector<double> MCHit_pathlength; @@ -470,6 +489,13 @@ void PrClustersResidual::TrackStudy(){ MCHit_ty.push_back(mcHit->dydz()); MCHit_p.push_back(mcHit->p()); MCHit_pathlength.push_back(mcHit->pathLength()); + + MCHit_EntryX.push_back(mcHit->entry().X()); + MCHit_EntryY.push_back(mcHit->entry().Y()); + MCHit_EntryZ.push_back(mcHit->entry().Z()); + MCHit_ExitX.push_back(mcHit->exit().X()); + MCHit_ExitY.push_back(mcHit->exit().Y()); + MCHit_ExitZ.push_back(mcHit->exit().Z()); MCHit_X.push_back(mcHit->midPoint().X()); MCHit_Y.push_back(mcHit->midPoint().Y()); MCHit_Z.push_back(mcHit->midPoint().Z()); @@ -523,6 +549,12 @@ void PrClustersResidual::TrackStudy(){ MCHit_time.push_back(-999999.); MCHit_Particle_key.push_back(-999999.); MCHit_pathlength.push_back(-999999.); + MCHit_EntryX.push_back(-999999.); + MCHit_EntryY.push_back(-999999.); + MCHit_EntryZ.push_back(-999999.); + MCHit_ExitX.push_back(-999999.); + MCHit_ExitY.push_back(-999999.); + MCHit_ExitZ.push_back(-999999.); MCHit_X.push_back(-999999.); MCHit_Y.push_back(-999999.); MCHit_Z.push_back(-999999.); @@ -545,6 +577,13 @@ void PrClustersResidual::TrackStudy(){ tuple->farray("MCHit_tx",MCHit_tx,"MC_ass",100); tuple->farray("MCHit_p",MCHit_p,"MC_ass",100); tuple->farray("MCHit_pathlength",MCHit_pathlength,"MC_ass",100); + tuple->farray("MCHit_Assoc_EntryX",MCHit_EntryX ,"MC_ass",100); + tuple->farray("MCHit_Assoc_EntryY",MCHit_EntryY ,"MC_ass",100); + tuple->farray("MCHit_Assoc_EntryZ",MCHit_EntryZ ,"MC_ass",100); + tuple->farray("MCHit_Assoc_ExitX",MCHit_ExitX ,"MC_ass",100); + tuple->farray("MCHit_Assoc_ExitY",MCHit_ExitY ,"MC_ass",100); + tuple->farray("MCHit_Assoc_ExitZ",MCHit_ExitZ ,"MC_ass",100); + tuple->farray("MCHit_Assoc_X",MCHit_X ,"MC_ass",100); tuple->farray("MCHit_Assoc_Y",MCHit_Y ,"MC_ass",100); tuple->farray("MCHit_Assoc_Z",MCHit_Z ,"MC_ass",100); @@ -1025,6 +1064,8 @@ void PrClustersResidual::ClusterResidual(){ if(msgLevel(MSG::DEBUG)) debug()<<"Loaded"<<endmsg; //took first MCHit associated to Hit channelID std::vector<double> MCHit_X,MCHit_Y,MCHit_Z; + std::vector<double> MCHit_EntryX, MCHit_EntryY, MCHit_EntryZ; + std::vector<double> MCHit_ExitX, MCHit_ExitY, MCHit_ExitZ; std::vector<double> Residual_X,Residual_Z; std::vector<double> SlopeX; std::vector<double> SlopeY; @@ -1040,15 +1081,25 @@ void PrClustersResidual::ClusterResidual(){ MCHit_X.push_back(-9999.); MCHit_Y.push_back(-9999.); MCHit_Z.push_back(-9999.); - SlopeX.push_back(-999.); - SlopeY.push_back(-999.); - pathlength.push_back(-999.); - energy.push_back( -999.); + MCHit_EntryX.push_back(-9999.); + MCHit_EntryY.push_back(-9999.); + MCHit_EntryZ.push_back(-9999.); + + MCHit_ExitX.push_back(-9999.); + MCHit_ExitY.push_back(-9999.); + MCHit_ExitZ.push_back(-9999.); + + SlopeX.push_back(-9999.); + SlopeY.push_back(-9999.); + pathlength.push_back(-9999.); + energy.push_back( -9999.); hit_Physics.push_back(false); } while(mcHit != nullptr){ nMCHitToCluster++; - Gaudi::XYZPoint pMid = mcHit->midPoint(); + auto pMid = mcHit->midPoint(); + auto pEntry = mcHit->entry(); + auto pExit = mcHit->exit(); Residual_X.push_back( (*iHit).x(pMid.y()) - pMid.x()); //x at y - y at z Residual_Z.push_back( (*iHit).z(pMid.y()) - pMid.z()); SlopeX.push_back( mcHit->dxdz()); @@ -1058,6 +1109,13 @@ void PrClustersResidual::ClusterResidual(){ MCHit_X.push_back( pMid.x()); MCHit_Y.push_back( pMid.y()); MCHit_Z.push_back( pMid.z()); + + MCHit_ExitX.push_back( pExit.x()); + MCHit_ExitY.push_back( pExit.y()); + MCHit_ExitZ.push_back( pExit.z()); + MCHit_EntryX.push_back( pEntry.x()); + MCHit_EntryY.push_back( pEntry.y()); + MCHit_EntryZ.push_back( pEntry.z()); //mcHit = myFTCluster2MCHitLink.next(); // const LHCb::MCParticle *mcPart = mcHit->mcParticle(); const LHCb::MCParticle *mcPart = mcHit->mcParticle(); @@ -1067,6 +1125,7 @@ void PrClustersResidual::ClusterResidual(){ if(mcPart!= nullptr){ if(msgLevel(MSG::DEBUG)) debug() <<"Getting Vertex"<<endmsg; const LHCb::MCVertex* vertex = mcPart->originVertex(); + //track of physical interest if the associated vertex is a Primary one or from Decay ( i.e. veto the interaction one ) if( vertex!=nullptr && (vertex->isPrimary() || vertex->isDecay())){ hit_Physics.push_back( true ); }else{ @@ -1077,7 +1136,6 @@ void PrClustersResidual::ClusterResidual(){ } if(msgLevel(MSG::DEBUG)) debug()<<"Storing vectors"<<endmsg; tuple->column("isNoiseCluster",isNoise); - tuple->farray("MCHit_Physics", hit_Physics.begin(),hit_Physics.end(),"N_MC",100); tuple->farray("CosSlopeX",SlopeX.begin(),SlopeX.end(),"N_MC",100); tuple->farray("CosSlopeY",SlopeY.begin(),SlopeY.end(),"N_MC",100); @@ -1088,6 +1146,15 @@ void PrClustersResidual::ClusterResidual(){ tuple->farray("MCHit_X",MCHit_X.begin(),MCHit_X.end(),"N_MC",100); tuple->farray("MCHit_Z",MCHit_Z.begin(),MCHit_Z.end(),"N_MC",100); tuple->farray("MCHit_Y",MCHit_Y.begin(),MCHit_Y.end(),"N_MC",100); + + tuple->farray("MCHit_EntryX",MCHit_EntryX.begin(),MCHit_EntryX.end(),"N_MC",100); + tuple->farray("MCHit_EntryZ",MCHit_EntryZ.begin(),MCHit_EntryZ.end(),"N_MC",100); + tuple->farray("MCHit_EntryY",MCHit_EntryY.begin(),MCHit_EntryY.end(),"N_MC",100); + tuple->farray("MCHit_ExitX",MCHit_ExitX.begin(),MCHit_ExitX.end(),"N_MC",100); + tuple->farray("MCHit_ExitZ",MCHit_ExitZ.begin(),MCHit_ExitZ.end(),"N_MC",100); + tuple->farray("MCHit_ExitY",MCHit_ExitY.begin(),MCHit_ExitY.end(),"N_MC",100); + + //here fill the tuple with watever you want //get Cluster associated to the Hit if(msgLevel(MSG::DEBUG)) debug()<<"Getting LiteCluster from PrHit"<<endmsg; @@ -1145,8 +1212,8 @@ void PrClustersResidual::ClusterResidual(){ tuple->column("Hit_Zone",(*iHit).zone()); tuple->column("Hit_dzDy_manually",((*iHit).z(1000.)-(*iHit).z(0.))/1000); //Get the list of tracks generated by the Hit i am lookign to - if(m_debugTracking) - { + if(m_debugTracking){ + //get linker Forward tracks and Seeding ones to see hit content! LinkedTo<LHCb::MCParticle, LHCb::Track> myForwardLink ( evtSvc(), msgSvc(),LHCb::TrackLocation::Forward); LinkedTo<LHCb::MCParticle, LHCb::Track> mySeedLink ( evtSvc(), msgSvc(),LHCb::TrackLocation::Seed); diff --git a/Pr/PrMCTools/src/PrClustersResidual.h b/Pr/PrMCTools/src/PrClustersResidual.h index 4ab37712b6..6c48866a67 100644 --- a/Pr/PrMCTools/src/PrClustersResidual.h +++ b/Pr/PrMCTools/src/PrClustersResidual.h @@ -23,7 +23,7 @@ #include "Event/Track.h" #include "Linker/LinkerTool.h" #include "PrKernel/IPrCounter.h" - +#include "FTDet/DeFTDetector.h" /** @class PrClustersResidual PrClustersResidual.h * Make nTuples of Cluster vs MCHits and Hit content on track + Occupancy study possible ( also in PrPlotFTHits ) * -MCHitsLocation : Where to find the MCHits ( /Event/MC/FT/FTHits by default ) @@ -103,39 +103,28 @@ private: std::vector<const LHCb::Track*> getTrack(const LHCb::LHCbID id, const std::string location); LHCb::FTLiteCluster getLiteCluster(const LHCb::LHCbID id); - std::string m_mcHitLocation; - std::string m_ftClusterToParticleLinkerLocation; - std::string m_ftClusterToHitLinkerLocation; - // unsigned int m_zone; - bool m_debugTracking; + Gaudi::Property<std::string> m_mcHitLocation {this, "MCHitsLocation", "/Event/MC/FT/Hits"}; + Gaudi::Property<std::string> m_ftClusterToParticleLinkerLocation { this, "FTClusterToParticleLinkerLocation", LHCb::FTLiteClusterLocation::Default + "WithSpillover"}; + Gaudi::Property<std::string> m_ftClusterToHitLinkerLocation { this, "FTClusterToHitLinkerLocation", LHCb::FTLiteClusterLocation::Default + "2MCHitsWithSpillover"}; + Gaudi::Property<std::string> m_hitManagerName { this, "HitManagerName", "PrFTHitManager"}; + Gaudi::Property<bool> m_debugTracking { this, "DebugTracking", false}; + Gaudi::Property<bool> m_doClusterResidual { this, "DoClusterResidual", false}; //Cluster residual tuple + Gaudi::Property<bool> m_doTrackStudy { this, "DoTrackStudy", false}; // Produce tuple for track studies + Gaudi::Property<bool> m_decodeData { this, "DecodeData", false}; //ask to decode data ( is False if other algorithms are runned + Gaudi::Property<bool> m_onlyHasT { this, "OnlyHasT",false}; //(keep only MCParticles with hasT = true + Gaudi::Property<bool> m_removeClones { this, "RemoveClones", true}; //Observed clones MCHits when processed ( not understood ) + Gaudi::Property<bool> m_dumpAllHits { this, "DumpAllHits", false }; //Dump in tuple for a given event all the hits + Gaudi::Property<bool> m_Occupancy { this, "Occupancy", true };// Produce Occupancy plot int m_nEvents; - double m_NClusters ; double m_NMCHit ; double m_NMCHit_inClusters; - bool m_onlyHasT; PrHitManager* m_ftHitManager; unsigned int m_zone; - bool m_decodeData; - bool m_removeClones; - bool m_dumpAllHits; - bool m_Occupancy; - std::string m_hitManagerName; - bool m_doClusterResidual; - bool m_doTrackStudy; - - //from PrCounter - // typedef LinkerTool<LHCb::Track, LHCb::MCParticle> MyAsct; - // typedef MyAsct::DirectType Table; - // typedef MyAsct::DirectType::Range Range; - // typedef Table::iterator iterator; - // typedef MyAsct::InverseType InvTable; - // typedef InvTable::Range InvRange; - // typedef InvTable::iterator InvIterator; - // MyAsct* m_link; - // const InvTable* m_invTable; + //need the ftDet to produce the pseudochannel conversion numbering in occupancy plot for v61 + DeFTDetector * m_ftDet = nullptr; }; #endif // PRCLUSTERSRESIDUAL_H -- GitLab From b051f41d4e90dcae4fa8582ed9088027b699c2c7 Mon Sep 17 00:00:00 2001 From: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Tue, 7 Mar 2017 10:10:11 +0000 Subject: [PATCH 57/68] Add CPU capabilities detector to Quartic reconstruction algorithm. Does not change much yet, but is in preparation for other future improvements --- .../CMakeLists.txt | 6 ++++-- .../src/RichQuarticPhotonReco.cpp | 17 ++++++++++------- .../src/RichQuarticPhotonReco.h | 3 +++ 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/Rich/RichFutureRecPhotonAlgorithms/CMakeLists.txt b/Rich/RichFutureRecPhotonAlgorithms/CMakeLists.txt index a226a88b4c..85678715d1 100644 --- a/Rich/RichFutureRecPhotonAlgorithms/CMakeLists.txt +++ b/Rich/RichFutureRecPhotonAlgorithms/CMakeLists.txt @@ -28,10 +28,12 @@ set_property(SOURCE src/sse4/RichQuarticPhotonReco.cpp APPEND_STRING PROPERT set_property(SOURCE src/avx/RichQuarticPhotonReco.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-ignored-attributes -O3 -mavx " ) -set_property(SOURCE src/avx2/RichQuarticPhotonReco.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-ignored-attributes -O3 -mavx2 -mfma " ) +# Until such a time that all build targets support AVX2+FMA, fallback to just AVX here +#set_property(SOURCE src/avx2/RichQuarticPhotonReco.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-ignored-attributes -O3 -mavx2 -mfma " ) +set_property(SOURCE src/avx2/RichQuarticPhotonReco.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-ignored-attributes -O3 -mavx " ) if(LCG_COMP STREQUAL "gcc" OR (BINARY_TAG_COMP_NAME STREQUAL "gcc" AND BINARY_TAG_COMP_VERSION VERSION_LESS "5")) - set_property(SOURCE src/avx/RichQuarticPhotonReco.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -fabi-version=0 " ) + set_property(SOURCE src/avx/RichQuarticPhotonReco.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -fabi-version=0 " ) set_property(SOURCE src/avx2/RichQuarticPhotonReco.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -fabi-version=0 " ) endif() diff --git a/Rich/RichFutureRecPhotonAlgorithms/src/RichQuarticPhotonReco.cpp b/Rich/RichFutureRecPhotonAlgorithms/src/RichQuarticPhotonReco.cpp index 9ca2553298..14f6b40195 100644 --- a/Rich/RichFutureRecPhotonAlgorithms/src/RichQuarticPhotonReco.cpp +++ b/Rich/RichFutureRecPhotonAlgorithms/src/RichQuarticPhotonReco.cpp @@ -48,13 +48,16 @@ StatusCode QuarticPhotonReco::initialize() if ( !sc ) return sc; // Get the CPU capabilities and set dispatch method - //enum CPUID { GENERIC = 0, SSE4 = 6, AVX = 7, AVX2 = 8 }; - //const auto cpuLevel = instrset_detect(); - //_ri_debug << "Instruction set level = " << cpuLevel << endmsg; - //if ( cpuLevel >= AVX2 ) { m_run = &QuarticPhotonReco::run_avx2; } - //else if ( cpuLevel >= AVX ) { m_run = &QuarticPhotonReco::run_avx; } - //else if ( cpuLevel >= SSE4 ) { m_run = &QuarticPhotonReco::run_sse4; } - //else { m_run = &QuarticPhotonReco::run_generic; } + if ( m_detectCPU ) + { + enum CPUID { GENERIC = 0, SSE4 = 6, AVX = 7, AVX2 = 8 }; + const auto cpuLevel = instrset_detect(); + _ri_debug << "Instruction set level = " << cpuLevel << endmsg; + if ( cpuLevel >= AVX2 ) { m_run = &QuarticPhotonReco::run_avx2; } + else if ( cpuLevel >= AVX ) { m_run = &QuarticPhotonReco::run_avx; } + else if ( cpuLevel >= SSE4 ) { m_run = &QuarticPhotonReco::run_sse4; } + else { m_run = &QuarticPhotonReco::run_generic; } + } // get the detector elements m_rich[Rich::Rich1] = getDet<DeRich>( DeRichLocations::Rich1 ); diff --git a/Rich/RichFutureRecPhotonAlgorithms/src/RichQuarticPhotonReco.h b/Rich/RichFutureRecPhotonAlgorithms/src/RichQuarticPhotonReco.h index 83b1baead2..565496df0e 100644 --- a/Rich/RichFutureRecPhotonAlgorithms/src/RichQuarticPhotonReco.h +++ b/Rich/RichFutureRecPhotonAlgorithms/src/RichQuarticPhotonReco.h @@ -318,6 +318,9 @@ namespace Rich ToolHandle<const IMirrorSegFinderLookUpTable> m_mirrorSegFinder { "Rich::Future::MirrorSegFinderLookUpTable/MirrorFinder:PUBLIC", this }; + /// Flag to control if CPU detection should be performed or not + Gaudi::Property<bool> m_detectCPU { this, "DetectCPUCapabilites", true }; + }; //========================================================================= -- GitLab From 608a6e80d4389386d7d97e81f4008903590aff2f Mon Sep 17 00:00:00 2001 From: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Tue, 7 Mar 2017 10:10:33 +0000 Subject: [PATCH 58/68] Disable AVX2+FMA until such a time as all build platforms can support it --- Rich/RichRecTests/CMakeLists.txt | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Rich/RichRecTests/CMakeLists.txt b/Rich/RichRecTests/CMakeLists.txt index 8ac0bf8ba3..2e13a4845a 100644 --- a/Rich/RichRecTests/CMakeLists.txt +++ b/Rich/RichRecTests/CMakeLists.txt @@ -55,7 +55,9 @@ if(GAUDI_BUILD_TESTS) INCLUDE_DIRS Kernel/TemplatedGenVector ROOT Vc Eigen GSL VectorClass src LINK_LIBRARIES LHCbMathLib GSL GaudiKernel TemplatedGenVectorLib ) target_link_libraries( RichPhotonRecoTestAVX2FMA -lrt ) - set_property(SOURCE src/PhotonReco/main_avx2fma.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -mfma -mavx2 " ) + # Until such a time that all build targets support AVX2+FMA, fallback to just AVX here + #set_property(SOURCE src/PhotonReco/main_avx2fma.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -mfma -mavx2 " ) + set_property(SOURCE src/PhotonReco/main_avx2fma.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -mavx " ) @@ -85,8 +87,9 @@ if(GAUDI_BUILD_TESTS) INCLUDE_DIRS Kernel/TemplatedGenVector ROOT Vc Eigen GSL VectorClass src LINK_LIBRARIES LHCbMathLib GSL GaudiKernel TemplatedGenVectorLib ) target_link_libraries( RichRayTracingTestAVX2FMA "-lrt ${Vc_LIB_DIR}/libVc.a" ) - set_property(SOURCE src/RayTracing/main_avx2fma.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-ignored-attributes -mfma -mavx2 " ) - + # Until such a time that all build targets support AVX2+FMA, fallback to just AVX here + #set_property(SOURCE src/RayTracing/main_avx2fma.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-ignored-attributes -mfma -mavx2 " ) + set_property(SOURCE src/RayTracing/main_avx2fma.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-ignored-attributes -mavx " ) if(LCG_COMP STREQUAL "gcc" OR (BINARY_TAG_COMP_NAME STREQUAL "gcc" AND BINARY_TAG_COMP_VERSION VERSION_LESS "5")) -- GitLab From df06ae2fd9e5368033e17fb6c3187229b1c5515e Mon Sep 17 00:00:00 2001 From: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Tue, 7 Mar 2017 14:55:13 +0000 Subject: [PATCH 59/68] Fix doxygen comments --- .../src/RichGlobalPIDNamespaces.h | 20 +++++++++++++++++++ .../RichFutureRecBase/RichRecNamespaces.h | 14 +++++++++++-- .../RichRecPhotonPredictedPixelSignals.h | 1 + .../RichFutureRecEvent/RichSummaryEventData.h | 18 ++++++++++++++++- .../src/RichQuarticPhotonReco.h | 1 + .../examples/Col16RawDataFiles.py | 3 +++ .../src/RichBaseTrSegMaker.h | 2 +- .../src/RichGeomEffCKMassRings.h | 2 +- .../RichTrackFunctionalCherenkovResolutions.h | 2 +- 9 files changed, 57 insertions(+), 6 deletions(-) create mode 100755 Rich/RichFutureGlobalPID/src/RichGlobalPIDNamespaces.h diff --git a/Rich/RichFutureGlobalPID/src/RichGlobalPIDNamespaces.h b/Rich/RichFutureGlobalPID/src/RichGlobalPIDNamespaces.h new file mode 100755 index 0000000000..d28f230cf0 --- /dev/null +++ b/Rich/RichFutureGlobalPID/src/RichGlobalPIDNamespaces.h @@ -0,0 +1,20 @@ + +//----------------------------------------------------------------------------- +/** @namespace Rich::Future::Rec::GlobalPID + * + * Namespace for RICH Global PID software + * + * @author Chris Jones Christopher.Rob.Jones@cern.ch + * @date 04/12/2006 + */ +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +/** @namespace Rich::Future::Rec::GlobalPID::MC + * + * Namespace for RICH Global PID MC related software + * + * @author Chris Jones Christopher.Rob.Jones@cern.ch + * @date 05/12/2006 + */ +//----------------------------------------------------------------------------- diff --git a/Rich/RichFutureRecBase/RichFutureRecBase/RichRecNamespaces.h b/Rich/RichFutureRecBase/RichFutureRecBase/RichRecNamespaces.h index c7472cd147..8443cac3c5 100644 --- a/Rich/RichFutureRecBase/RichFutureRecBase/RichRecNamespaces.h +++ b/Rich/RichFutureRecBase/RichFutureRecBase/RichRecNamespaces.h @@ -5,7 +5,7 @@ * General namespace for all RICH reconstruction software * * @author Chris Jones Christopher.Rob.Jones@cern.ch - * @date 08/07/2004 + * @date 01/02/2017 */ //----------------------------------------------------------------------------- @@ -15,6 +15,16 @@ * General namespace for RICH reconstruction MC related software * * @author Chris Jones Christopher.Rob.Jones@cern.ch - * @date 05/12/2006 + * @date 01/02/2017 + */ +//----------------------------------------------------------------------------- + +//----------------------------------------------------------------------------- +/** @namespace Rich::Future::Rec::Moni + * + * General namespace for RICH reconstruction monitoring utilities + * + * @author Chris Jones Christopher.Rob.Jones@cern.ch + * @date 01/02/2017 */ //----------------------------------------------------------------------------- diff --git a/Rich/RichFutureRecEvent/RichFutureRecEvent/RichRecPhotonPredictedPixelSignals.h b/Rich/RichFutureRecEvent/RichFutureRecEvent/RichRecPhotonPredictedPixelSignals.h index 45351b5eed..d7391683b5 100644 --- a/Rich/RichFutureRecEvent/RichFutureRecEvent/RichRecPhotonPredictedPixelSignals.h +++ b/Rich/RichFutureRecEvent/RichFutureRecEvent/RichRecPhotonPredictedPixelSignals.h @@ -24,6 +24,7 @@ namespace Rich /// Type for flags to say if a photon is active or not. i.e. has any signal. using PhotonFlags = LHCb::STL::Vector<bool>; + /// photon active flags TES locations namespace PhotonActiveFlagsLocation { /// Location in TES for the active photon flags diff --git a/Rich/RichFutureRecEvent/RichFutureRecEvent/RichSummaryEventData.h b/Rich/RichFutureRecEvent/RichFutureRecEvent/RichSummaryEventData.h index 0c5854a240..2c322afa97 100644 --- a/Rich/RichFutureRecEvent/RichFutureRecEvent/RichSummaryEventData.h +++ b/Rich/RichFutureRecEvent/RichFutureRecEvent/RichSummaryEventData.h @@ -24,6 +24,14 @@ namespace Rich { // =========================================================================== + /** @namespace Summary + * + * General namespace for RICH reconstruction summary information + * + * @author Chris Jones Christopher.Rob.Jones@cern.ch + * @date 01/02/2017 + */ + namespace Summary { @@ -125,6 +133,14 @@ namespace Rich // =========================================================================== + /** @class Pixel RichSummaryEventData.h + * + * Summary of the immutable pixell data. + * + * @author Chris Jones + * @date 2016-09-30 + */ + class Pixel final { @@ -155,7 +171,7 @@ namespace Rich // =========================================================================== - /// TES locations + /// Summary information TES locations namespace TESLocations { /// Tracks diff --git a/Rich/RichFutureRecPhotonAlgorithms/src/RichQuarticPhotonReco.h b/Rich/RichFutureRecPhotonAlgorithms/src/RichQuarticPhotonReco.h index 565496df0e..5eff019747 100644 --- a/Rich/RichFutureRecPhotonAlgorithms/src/RichQuarticPhotonReco.h +++ b/Rich/RichFutureRecPhotonAlgorithms/src/RichQuarticPhotonReco.h @@ -159,6 +159,7 @@ namespace Rich const SpacePointVector& globalPoints, const SpacePointVector& localPoints, const Relations::TrackToSegments::Vector& tkToSegRels ) const; + /// AVX2 method OutData run_avx2( const LHCb::RichTrackSegment::Vector& segments, const CherenkovAngles::Vector& ckAngles, diff --git a/Rich/RichFutureRecSys/examples/Col16RawDataFiles.py b/Rich/RichFutureRecSys/examples/Col16RawDataFiles.py index 93f5018ebe..c56359d4d3 100644 --- a/Rich/RichFutureRecSys/examples/Col16RawDataFiles.py +++ b/Rich/RichFutureRecSys/examples/Col16RawDataFiles.py @@ -21,3 +21,6 @@ from Configurables import Brunel, LHCbApp Brunel().DataType = "2016" Brunel().Simulation = False Brunel().WithMC = False + +#Brunel().DDDBtag = "dddb-20150724" +#Brunel().CondDBtag = "cond-20161011" diff --git a/Rich/RichFutureRecTrackAlgorithms/src/RichBaseTrSegMaker.h b/Rich/RichFutureRecTrackAlgorithms/src/RichBaseTrSegMaker.h index 2aa35f224f..f4dc7eaec5 100755 --- a/Rich/RichFutureRecTrackAlgorithms/src/RichBaseTrSegMaker.h +++ b/Rich/RichFutureRecTrackAlgorithms/src/RichBaseTrSegMaker.h @@ -49,7 +49,7 @@ namespace Rich { //--------------------------------------------------------------------------------- - /** @class BaseTrSegMakerFromRecoTracks RichBaseTrSegMakerFromRecoTracks.h + /** @class BaseTrSegMaker RichBaseTrSegMaker.h * * Base class to tools that create RichTrackSegments from Tracks. * diff --git a/Rich/RichFutureRecTrackAlgorithms/src/RichGeomEffCKMassRings.h b/Rich/RichFutureRecTrackAlgorithms/src/RichGeomEffCKMassRings.h index 66423a3cf4..67e050fba0 100644 --- a/Rich/RichFutureRecTrackAlgorithms/src/RichGeomEffCKMassRings.h +++ b/Rich/RichFutureRecTrackAlgorithms/src/RichGeomEffCKMassRings.h @@ -42,7 +42,7 @@ namespace Rich SegmentPhotonFlags::Vector >; } - /** @class RichGeomEffCKMassRings RichRichGeomEffCKMassRings.h + /** @class GeomEffCKMassRings RichRichGeomEffCKMassRings.h * * Computes the geometrical efficiencies for a set of track segments. * diff --git a/Rich/RichFutureRecTrackAlgorithms/src/RichTrackFunctionalCherenkovResolutions.h b/Rich/RichFutureRecTrackAlgorithms/src/RichTrackFunctionalCherenkovResolutions.h index c5f3e88bef..3072c9e114 100644 --- a/Rich/RichFutureRecTrackAlgorithms/src/RichTrackFunctionalCherenkovResolutions.h +++ b/Rich/RichFutureRecTrackAlgorithms/src/RichTrackFunctionalCherenkovResolutions.h @@ -53,7 +53,7 @@ namespace Rich namespace Rec { - /** @class FunctionalCherenkovResolutions RichRichTrackFunctionalCherenkovResolutions.h + /** @class TrackFunctionalCherenkovResolutions RichTrackFunctionalCherenkovResolutions.h * * Computes the expected Cherenkov resolutions for the given track segments * -- GitLab From c5bd3a6a2ff92758afa0b0722d3ceaa62147aadb Mon Sep 17 00:00:00 2001 From: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Tue, 7 Mar 2017 16:09:55 +0000 Subject: [PATCH 60/68] cleanup --- Rich/RichFutureRecPhotonAlgorithms/src/RichQuarticPhotonReco.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Rich/RichFutureRecPhotonAlgorithms/src/RichQuarticPhotonReco.h b/Rich/RichFutureRecPhotonAlgorithms/src/RichQuarticPhotonReco.h index 5eff019747..41125b129d 100644 --- a/Rich/RichFutureRecPhotonAlgorithms/src/RichQuarticPhotonReco.h +++ b/Rich/RichFutureRecPhotonAlgorithms/src/RichQuarticPhotonReco.h @@ -124,7 +124,7 @@ namespace Rich const Rich::PDPixelCluster::Vector& clusters, const SpacePointVector& globalPoints, const SpacePointVector& localPoints, - const Relations::TrackToSegments::Vector& tkToSegRels ) const + const Relations::TrackToSegments::Vector& tkToSegRels ) const = &QuarticPhotonReco::run_generic; /// Generic method -- GitLab From 4e36eddc85d034dbc8d9e624a5aa0c6e8fc463b6 Mon Sep 17 00:00:00 2001 From: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Tue, 7 Mar 2017 16:10:52 +0000 Subject: [PATCH 61/68] Add simple ROOT macro script for RICH correlation studies --- Rec/GlobalReco/root/RichCorrelations.C | 66 ++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 Rec/GlobalReco/root/RichCorrelations.C diff --git a/Rec/GlobalReco/root/RichCorrelations.C b/Rec/GlobalReco/root/RichCorrelations.C new file mode 100644 index 0000000000..96d0e67575 --- /dev/null +++ b/Rec/GlobalReco/root/RichCorrelations.C @@ -0,0 +1,66 @@ + +#include <memory> + +void RichCorrelations() +{ + + auto c = std::make_unique<TCanvas>( "RichCor", "RichCor", 1400, 1000 ); + + TTree tree; + + tree.AddFriend("hlt2 = ChargedProtoTuple/protoPtuple", + "/usera/jonesc/LHCbCMake/Brunel/output/future/Quartic100R1R2-AllHypos/protoparticles.tuples.root"); + + //tree.AddFriend("hlt1 = ChargedProtoTuple/protoPtuple", "/usera/jonesc/LHCbCMake/Brunel/output/future/FastQuartic50R1R2-AllHypos-NoUnAmBigPhot-NoBeamPipeCheck-1It/protoparticles.tuples.root"); + //tree.AddFriend("hlt1 = ChargedProtoTuple/protoPtuple", "/usera/jonesc/LHCbCMake/Brunel/output/future/CKEsti50R1R2-KaPi/protoparticles.tuples.root"); + tree.AddFriend("hlt1 = ChargedProtoTuple/protoPtuple", "/usera/jonesc/LHCbCMake/Brunel/output/future/CKEsti50R1R2-AllHypos/protoparticles.tuples.root"); + + tree.Draw("hlt2.TrackP:hlt1.TrackP","hlt2.TrackP<100000","zcol"); + c->SaveAs( "P-Correlations.pdf" ); + + auto sel = TCut("hlt2.RichAbovePiThres>0 && hlt1.RichAbovePiThres>0 && hlt2.TrackP<100000 && hlt2.TrackP>3000"); + + auto trueK = TCut("abs(hlt2.MCParticleType) == 321"); + + auto truePi = TCut("abs(hlt2.MCParticleType) == 211"); + + tree.Draw( "hlt2.RichDLLk:hlt1.RichDLLk",sel && trueK,"zcol"); + c->SaveAs( "TrueK-RichDLLk-2dCorrelations.pdf" ); + + tree.Draw( "hlt2.RichDLLk-hlt1.RichDLLk",sel && trueK ); + c->SaveAs( "TrueK-RichDLLk-1dCorrelations.pdf" ); + + tree.Draw( "hlt1.RichDLLk", sel ); + c->SaveAs( "All-RichDLLk-HLT1.pdf" ); + + tree.Draw( "hlt2.RichDLLk", sel ); + c->SaveAs( "All-RichDLLk-HLT2.pdf" ); + + tree.Draw( "hlt1.RichDLLk", sel && trueK ); + c->SaveAs( "TrueK-RichDLLk-HLT1.pdf" ); + + tree.Draw( "hlt2.RichDLLk", sel && trueK ); + c->SaveAs( "TrueK-RichDLLk-HLT2.pdf" ); + + tree.Draw( "hlt1.RichDLLk", sel && truePi ); + c->SaveAs( "TruePi-RichDLLk-HLT1.pdf" ); + + tree.Draw( "hlt2.RichDLLk", sel && truePi ); + c->SaveAs( "TruePi-RichDLLk-HLT2.pdf" ); + + tree.Draw( "hlt1.RichDLLk", sel && trueK && TCut("hlt2.RichDLLk>-2") ); + c->SaveAs( "TrueK-RichDLLk-HLT1-HLT2gt-2.pdf" ); + + tree.Draw( "hlt1.RichDLLk", sel && trueK && TCut("hlt2.RichDLLk>0") ); + c->SaveAs( "TrueK-RichDLLk-HLT1-HLT2gt0.pdf" ); + + tree.Draw( "hlt1.RichDLLk", sel && trueK && TCut("hlt2.RichDLLk>2") ); + c->SaveAs( "TrueK-RichDLLk-HLT1-HLT2gt2.pdf" ); + + tree.Draw( "hlt1.RichDLLk", sel && trueK && TCut("hlt2.RichDLLk>4") ); + c->SaveAs( "TrueK-RichDLLk-HLT1-HLT2gt4.pdf" ); + + tree.Draw( "hlt1.RichDLLk", sel && trueK && TCut("hlt2.RichDLLk>10") ); + c->SaveAs( "TrueK-RichDLLk-HLT1-HLT2gt10.pdf" ); + +} -- GitLab From 7d8defd5ff03b8535cdc499965fd5c4ead4318c1 Mon Sep 17 00:00:00 2001 From: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Tue, 7 Mar 2017 19:05:59 +0000 Subject: [PATCH 62/68] update photon reco test code to make seperate float and double containers --- Rich/RichRecTests/src/PhotonReco/main.icpp | 53 +++++++++++++--------- 1 file changed, 31 insertions(+), 22 deletions(-) diff --git a/Rich/RichRecTests/src/PhotonReco/main.icpp b/Rich/RichRecTests/src/PhotonReco/main.icpp index 91a02a4784..0888834dbf 100644 --- a/Rich/RichRecTests/src/PhotonReco/main.icpp +++ b/Rich/RichRecTests/src/PhotonReco/main.icpp @@ -17,7 +17,8 @@ // Make an instance of the quartic solver Rich::Rec::QuarticSolverNewton qSolver; -Gaudi::XYZPoint sphReflPoint; +ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D<float> > sphReflPointF; +ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D<double> > sphReflPointD; unsigned long long int time_diff( struct timespec *start, struct timespec *stop ) @@ -31,25 +32,26 @@ unsigned long long int time_diff( struct timespec *start, } } +template< typename TYPE > class Data { public: typedef std::vector<Data> Vector; public: - Gaudi::XYZPoint emissPnt; - Gaudi::XYZPoint centOfCurv; - Gaudi::XYZPoint virtDetPoint; - double radius; + ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D<TYPE> > emissPnt; + ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D<TYPE> > centOfCurv; + ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D<TYPE> > virtDetPoint; + TYPE radius; public: Data() { // randomn generator static std::default_random_engine gen; // Distributions for each member - static std::uniform_real_distribution<double> r_emiss_x(-800,800), r_emiss_y(-600,600), r_emiss_z(10000,10500); - static std::uniform_real_distribution<double> r_coc_x(-3000,3000), r_coc_y(-20,20), r_coc_z(3300,3400); - static std::uniform_real_distribution<double> r_vdp_x(-3000,3000), r_vdp_y(-200,200), r_vdp_z(8100,8200); - static std::uniform_real_distribution<float> r_rad(8500,8600); + static std::uniform_real_distribution<TYPE> r_emiss_x(-800,800), r_emiss_y(-600,600), r_emiss_z(10000,10500); + static std::uniform_real_distribution<TYPE> r_coc_x(-3000,3000), r_coc_y(-20,20), r_coc_z(3300,3400); + static std::uniform_real_distribution<TYPE> r_vdp_x(-3000,3000), r_vdp_y(-200,200), r_vdp_z(8100,8200); + static std::uniform_real_distribution<TYPE> r_rad(8500,8600); // setup data emissPnt = Gaudi::XYZPoint( r_emiss_x(gen), r_emiss_y(gen), r_emiss_z(gen) ); centOfCurv = Gaudi::XYZPoint( r_coc_x(gen), r_coc_y(gen), r_coc_z(gen) ); @@ -58,8 +60,8 @@ public: } }; -template< class TYPE > -inline void solve( const Data& data ) +template< class TYPE, class POINT > +inline void solve( const Data<TYPE>& data, POINT & sphReflPoint ) { qSolver.solve<TYPE,2,2>( data.emissPnt, data.centOfCurv, @@ -68,8 +70,9 @@ inline void solve( const Data& data ) sphReflPoint ); } -template< class TYPE > -unsigned long long int __attribute__((noinline)) solve( const Data::Vector & dataV ) +template< class TYPE, class POINT > +unsigned long long int __attribute__((noinline)) +solve( const typename Data<TYPE>::Vector & dataV, POINT & sphReflPoint ) { unsigned long long int best_dur{ 99999999999999999 }; @@ -80,7 +83,7 @@ unsigned long long int __attribute__((noinline)) solve( const Data::Vector & dat { clock_gettime(CLOCK_MONOTONIC_RAW,&start); // iterate over the data and solve it... - for ( const auto& data : dataV ) { solve<TYPE>(data); } + for ( const auto& data : dataV ) { solve<TYPE>(data,sphReflPoint); } clock_gettime(CLOCK_MONOTONIC_RAW,&end); const auto duration = time_diff(&start,&end); if ( duration < best_dur ) { best_dur = duration; } @@ -93,20 +96,26 @@ int main ( int /*argc*/, char** /*argv*/ ) { const unsigned int nPhotons = 1e5; - Data::Vector dataV; - dataV.reserve( nPhotons ); + Data<double>::Vector dataVD; + Data<float>::Vector dataVF; + dataVD.reserve( nPhotons ); + dataVF.reserve( nPhotons ); // Construct the data to work on std::cout << "Creating " << nPhotons << " random photons ..." << std::endl; - for ( unsigned int i = 0; i < nPhotons; ++i ) { dataV.push_back( Data() ); } - - // run the solver for floats - auto fTime = solve<float>( dataV ); - std::cout << "Float " << fTime << std::endl; + for ( unsigned int i = 0; i < nPhotons; ++i ) + { + dataVD.emplace_back( ); + dataVF.emplace_back( ); + } // run the solver for doubles - auto dTime = solve<double>( dataV ); + auto dTime = solve<double>( dataVD, sphReflPointD ); std::cout << "Double " << dTime << std::endl; + // run the solver for floats + auto fTime = solve<float>( dataVF, sphReflPointF ); + std::cout << "Float " << fTime << std::endl; + // make sure we are not optimized away asm volatile ("" : "+x"(fTime)); asm volatile ("" : "+x"(dTime)); -- GitLab From 0228508d170e0c04e0b2c277e133b27c48cce10f Mon Sep 17 00:00:00 2001 From: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Tue, 7 Mar 2017 19:47:26 +0000 Subject: [PATCH 63/68] Update template ranges --- .../src/RichQuarticPhotonReco.h | 5 ++++- .../src/RichQuarticPhotonReco.icpp | 4 ++-- Rich/RichRecTests/src/PhotonReco/main.icpp | 2 +- Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h | 11 ++++------- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/Rich/RichFutureRecPhotonAlgorithms/src/RichQuarticPhotonReco.h b/Rich/RichFutureRecPhotonAlgorithms/src/RichQuarticPhotonReco.h index 41125b129d..a5a3b1e54d 100644 --- a/Rich/RichFutureRecPhotonAlgorithms/src/RichQuarticPhotonReco.h +++ b/Rich/RichFutureRecPhotonAlgorithms/src/RichQuarticPhotonReco.h @@ -44,6 +44,9 @@ // Vector Class #include "VectorClass/instrset.h" +// VDT +#include "vdt/asin.h" + namespace Rich { namespace Future @@ -196,7 +199,7 @@ namespace Rich Gaudi::XYZPoint & secReflPoint ) const { // solve quartic equation with nominal values and find spherical mirror reflection point - m_quarticSolver.solve<double,2,2>( emissionPoint, + m_quarticSolver.solve<double,3,3>( emissionPoint, m_rich[rich]->nominalCentreOfCurvature(side), virtDetPoint, m_rich[rich]->sphMirrorRadius(), diff --git a/Rich/RichFutureRecPhotonAlgorithms/src/RichQuarticPhotonReco.icpp b/Rich/RichFutureRecPhotonAlgorithms/src/RichQuarticPhotonReco.icpp index dd4cb6f94b..2da9b16e53 100644 --- a/Rich/RichFutureRecPhotonAlgorithms/src/RichQuarticPhotonReco.icpp +++ b/Rich/RichFutureRecPhotonAlgorithms/src/RichQuarticPhotonReco.icpp @@ -333,7 +333,7 @@ virtDetPoint = gloPos - 2.0 * distance * secSegment->centreNormal(); // solve the quartic using the new data - m_quarticSolver.solve<double,2,3>( emissionPoint, + m_quarticSolver.solve<double,3,4>( emissionPoint, sphSegment->centreOfCurvature(), virtDetPoint, sphSegment->radius(), @@ -384,7 +384,7 @@ virtDetPoint = gloPos - 2.0 * distance * plane.Normal(); // solve the quartic using the new data - m_quarticSolver.solve<double,2,3>( emissionPoint, + m_quarticSolver.solve<double,3,4>( emissionPoint, sphSegment->centreOfCurvature(), virtDetPoint, sphSegment->radius(), diff --git a/Rich/RichRecTests/src/PhotonReco/main.icpp b/Rich/RichRecTests/src/PhotonReco/main.icpp index 0888834dbf..9373a35608 100644 --- a/Rich/RichRecTests/src/PhotonReco/main.icpp +++ b/Rich/RichRecTests/src/PhotonReco/main.icpp @@ -63,7 +63,7 @@ public: template< class TYPE, class POINT > inline void solve( const Data<TYPE>& data, POINT & sphReflPoint ) { - qSolver.solve<TYPE,2,2>( data.emissPnt, + qSolver.solve<TYPE,3,2>( data.emissPnt, data.centOfCurv, data.virtDetPoint, data.radius, diff --git a/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h b/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h index 8a83c1c857..00b5d47c42 100755 --- a/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h +++ b/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h @@ -20,9 +20,6 @@ #include <type_traits> #include <array> -// VDT -#include "vdt/asin.h" - namespace Rich { namespace Rec @@ -58,7 +55,7 @@ namespace Rich * @retval false Calculation failed. sphReflPoint is not valid. */ template< class TYPE, - std::size_t BISECTITS = 2, std::size_t NEWTONITS = 3, + std::size_t BISECTITS = 3, std::size_t NEWTONITS = 4, class POINT = Gaudi::XYZPoint > inline void solve( const POINT& emissionPoint, const POINT& CoC, @@ -278,7 +275,7 @@ namespace Rich * TODO: These tuning parameters have been found by low effort experimentation on random input data. A more detailed * study should be done with real data to find the best values */ - template < class TYPE, std::size_t BISECTITS = 2, std::size_t NEWTONITS = 3 > + template < class TYPE, std::size_t BISECTITS = 3, std::size_t NEWTONITS = 4 > inline TYPE solve_quartic_newton_RICH( const TYPE& a0, const TYPE& a1, const TYPE& a2, @@ -291,7 +288,7 @@ namespace Rich TYPE m(0.2); //We start a bit off center since the distribution of roots tends to be more to the left side const TYPE a[5] = {a0, a1, a2, a3, a4}; TYPE res[2]; - for ( std::size_t i = 0; i <= BISECTITS; ++i ) + for ( std::size_t i = 0; i < BISECTITS; ++i ) { const auto oppositeSign = std::signbit(f4(a0,a1,a2,a3,a4,m) * f4(a0,a1,a2,a3,a4,l)); @@ -313,7 +310,7 @@ namespace Rich //away with 3 iterations if we can find an exact value const TYPE gain = 1.04; - for ( std::size_t i = 0; i <= NEWTONITS; ++i ) + for ( std::size_t i = 0; i < NEWTONITS; ++i ) { evalPolyHorner<TYPE, 4, 1>( a, res, m ); //epsilon = f4(a0,a1,a2,a3,a4,x) / df4(a0,a1,a2,a3,x); -- GitLab From 9db641492d78062e15fe0f21c8d0c59e10cf7065 Mon Sep 17 00:00:00 2001 From: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Wed, 8 Mar 2017 10:05:38 +0000 Subject: [PATCH 64/68] Disable AVX2 in AVX2 only test builds as well as AVX2+FMA --- Rich/RichRecTests/CMakeLists.txt | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/Rich/RichRecTests/CMakeLists.txt b/Rich/RichRecTests/CMakeLists.txt index 2e13a4845a..5a43b8ec44 100644 --- a/Rich/RichRecTests/CMakeLists.txt +++ b/Rich/RichRecTests/CMakeLists.txt @@ -48,7 +48,9 @@ if(GAUDI_BUILD_TESTS) INCLUDE_DIRS Kernel/TemplatedGenVector ROOT Vc Eigen GSL VectorClass src LINK_LIBRARIES LHCbMathLib GSL GaudiKernel TemplatedGenVectorLib ) target_link_libraries( RichPhotonRecoTestAVX2 -lrt ) - set_property(SOURCE src/PhotonReco/main_avx2.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -mavx2 " ) + # Until such a time that all build targets support AVX2+FMA, fallback to just AVX here + #set_property(SOURCE src/PhotonReco/main_avx2.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -mavx2 " ) + set_property(SOURCE src/PhotonReco/main_avx2.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -mavx " ) gaudi_add_executable(RichPhotonRecoTestAVX2FMA src/PhotonReco/main_avx2fma.cpp @@ -80,7 +82,9 @@ if(GAUDI_BUILD_TESTS) INCLUDE_DIRS Kernel/TemplatedGenVector ROOT Vc Eigen GSL VectorClass src LINK_LIBRARIES LHCbMathLib GSL GaudiKernel TemplatedGenVectorLib ) target_link_libraries( RichRayTracingTestAVX2 "-lrt ${Vc_LIB_DIR}/libVc.a" ) - set_property(SOURCE src/RayTracing/main_avx2.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-ignored-attributes -mavx2 " ) + # Until such a time that all build targets support AVX2+FMA, fallback to just AVX here + #set_property(SOURCE src/RayTracing/main_avx2.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-ignored-attributes -mavx2 " ) + set_property(SOURCE src/RayTracing/main_avx2.cpp APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-ignored-attributes -mavx " ) gaudi_add_executable(RichRayTracingTestAVX2FMA src/RayTracing/main_avx2fma.cpp -- GitLab From 57cd213801e93a218b8a5820971fc4cdabc5c890 Mon Sep 17 00:00:00 2001 From: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Wed, 8 Mar 2017 14:46:16 +0000 Subject: [PATCH 65/68] Optimise the reflection of the detection point in the virtual secondary plane --- .../src/RichQuarticPhotonReco.icpp | 24 ++++++++++++------- .../RichRecUtils/QuarticSolverNewton.h | 4 +--- 2 files changed, 17 insertions(+), 11 deletions(-) diff --git a/Rich/RichFutureRecPhotonAlgorithms/src/RichQuarticPhotonReco.icpp b/Rich/RichFutureRecPhotonAlgorithms/src/RichQuarticPhotonReco.icpp index 2da9b16e53..a634b24086 100644 --- a/Rich/RichFutureRecPhotonAlgorithms/src/RichQuarticPhotonReco.icpp +++ b/Rich/RichFutureRecPhotonAlgorithms/src/RichQuarticPhotonReco.icpp @@ -161,8 +161,8 @@ // find the reflection of the detection point in the sec mirror // (virtual detection point) starting with nominal values // At this we are assuming a flat nominal mirror common to all segments - auto distance = m_rich[rich]->nominalPlane(side).Distance(gloPos); - auto virtDetPoint = gloPos - 2.0 * distance * m_rich[rich]->nominalNormal(side); + const auto nom_dist = m_rich[rich]->nominalPlane(side).Distance(gloPos); + auto virtDetPoint = gloPos - 2.0 * nom_dist * m_rich[rich]->nominalNormal(side); // -------------------------------------------------------------------------------------- // For gas radiators, try start and end points to see if photon is unambiguous @@ -329,7 +329,7 @@ { // Form the virtual detection point - distance = secSegment->centreNormalPlane().Distance(gloPos); + const auto distance = secSegment->centreNormalPlane().Distance(gloPos); virtDetPoint = gloPos - 2.0 * distance * secSegment->centreNormal(); // solve the quartic using the new data @@ -375,14 +375,22 @@ // (re)find the secondary mirror secSegment = m_mirrorSegFinder.get()->findSecMirror( rich, side, secReflPoint ); + // Compute the virtual reflection point + // Construct plane tangential to secondary mirror passing through reflection point - const Gaudi::Plane3D plane( secSegment->centreOfCurvature()-secReflPoint, secReflPoint ); - + //const Gaudi::Plane3D plane( secSegment->centreOfCurvature()-secReflPoint, secReflPoint ); // re-find the reflection of the detection point in the sec mirror // (virtual detection point) with this mirror plane - distance = plane.Distance(gloPos); - virtDetPoint = gloPos - 2.0 * distance * plane.Normal(); - + //const auto distance = plane.Distance(gloPos); + //virtDetPoint = gloPos - 2.0 * distance * plane.Normal(); + + // Same as above, just written out by hand and simplified a bit + const auto normV = secSegment->centreOfCurvature() - secReflPoint; + const auto distance = ( ( normV.X() * ( gloPos.X() - secReflPoint.X() ) ) + + ( normV.Y() * ( gloPos.Y() - secReflPoint.Y() ) ) + + ( normV.Z() * ( gloPos.Z() - secReflPoint.Z() ) ) ); + virtDetPoint = gloPos - 2.0 * distance * normV / normV.Mag2(); + // solve the quartic using the new data m_quarticSolver.solve<double,3,4>( emissionPoint, sphSegment->centreOfCurvature(), diff --git a/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h b/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h index 00b5d47c42..dfc5da3a9f 100755 --- a/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h +++ b/Rich/RichRecUtils/RichRecUtils/QuarticSolverNewton.h @@ -65,9 +65,6 @@ namespace Rich { using namespace std; - // typedefs vectorised types - using Vec4x = typename std::conditional<std::is_same<TYPE,float>::value,Vec4f,Vec4d>::type; - // vector from mirror centre of curvature to assumed emission point const auto evec( emissionPoint - CoC ); const TYPE e2 = evec.Dot(evec); @@ -81,6 +78,7 @@ namespace Rich const TYPE ed2 = e2 * d2; const TYPE cosgamma2 = ( ed2 > TYPE(0.0) ? pow(evec.Dot(dvec),2)/ed2 : TYPE(1.0) ); // vectorise 4 square roots into 1 + using Vec4x = typename std::conditional<std::is_same<TYPE,float>::value,Vec4f,Vec4d>::type; const auto tmp_sqrt = sqrt( Vec4x( e2, d2, cosgamma2 < TYPE(1.0) ? TYPE(1.0)-cosgamma2 : TYPE(0.0), cosgamma2 ) ); -- GitLab From 9c01bf5e5b5c4383a666d257bdd6a39e94cbfc75 Mon Sep 17 00:00:00 2001 From: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Wed, 8 Mar 2017 14:47:13 +0000 Subject: [PATCH 66/68] Remove Gaudi::XYZPoint construction --- Rich/RichRecTests/src/PhotonReco/main.icpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Rich/RichRecTests/src/PhotonReco/main.icpp b/Rich/RichRecTests/src/PhotonReco/main.icpp index 9373a35608..dbc074555b 100644 --- a/Rich/RichRecTests/src/PhotonReco/main.icpp +++ b/Rich/RichRecTests/src/PhotonReco/main.icpp @@ -53,9 +53,9 @@ public: static std::uniform_real_distribution<TYPE> r_vdp_x(-3000,3000), r_vdp_y(-200,200), r_vdp_z(8100,8200); static std::uniform_real_distribution<TYPE> r_rad(8500,8600); // setup data - emissPnt = Gaudi::XYZPoint( r_emiss_x(gen), r_emiss_y(gen), r_emiss_z(gen) ); - centOfCurv = Gaudi::XYZPoint( r_coc_x(gen), r_coc_y(gen), r_coc_z(gen) ); - virtDetPoint = Gaudi::XYZPoint( r_vdp_x(gen), r_vdp_y(gen), r_vdp_z(gen) ); + emissPnt = { r_emiss_x(gen), r_emiss_y(gen), r_emiss_z(gen) }; + centOfCurv = { r_coc_x(gen), r_coc_y(gen), r_coc_z(gen) }; + virtDetPoint = { r_vdp_x(gen), r_vdp_y(gen), r_vdp_z(gen) }; radius = r_rad(gen); } }; -- GitLab From c580bf1e9296f7f9d7f98648f62520e0e7bca210 Mon Sep 17 00:00:00 2001 From: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Wed, 8 Mar 2017 14:52:41 +0000 Subject: [PATCH 67/68] reorder the calculation to make sure the vector is scaled only once --- .../src/RichQuarticPhotonReco.icpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Rich/RichFutureRecPhotonAlgorithms/src/RichQuarticPhotonReco.icpp b/Rich/RichFutureRecPhotonAlgorithms/src/RichQuarticPhotonReco.icpp index a634b24086..63eb84b8e5 100644 --- a/Rich/RichFutureRecPhotonAlgorithms/src/RichQuarticPhotonReco.icpp +++ b/Rich/RichFutureRecPhotonAlgorithms/src/RichQuarticPhotonReco.icpp @@ -389,7 +389,7 @@ const auto distance = ( ( normV.X() * ( gloPos.X() - secReflPoint.X() ) ) + ( normV.Y() * ( gloPos.Y() - secReflPoint.Y() ) ) + ( normV.Z() * ( gloPos.Z() - secReflPoint.Z() ) ) ); - virtDetPoint = gloPos - 2.0 * distance * normV / normV.Mag2(); + virtDetPoint = gloPos - ( normV * ( 2.0 * distance / normV.Mag2() ) ); // solve the quartic using the new data m_quarticSolver.solve<double,3,4>( emissionPoint, -- GitLab From e884189fd705d30d2c1ac43a3f2987b8aa90f49b Mon Sep 17 00:00:00 2001 From: Chris Jones <jonesc@hep.phy.cam.ac.uk> Date: Wed, 8 Mar 2017 16:37:00 +0000 Subject: [PATCH 68/68] template floating point type in checkAngles and reorder cuts to place most likely to reject first --- .../src/RichBasePhotonReco.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Rich/RichFutureRecPhotonAlgorithms/src/RichBasePhotonReco.h b/Rich/RichFutureRecPhotonAlgorithms/src/RichBasePhotonReco.h index ff0522a364..09fadbbfe2 100644 --- a/Rich/RichFutureRecPhotonAlgorithms/src/RichBasePhotonReco.h +++ b/Rich/RichFutureRecPhotonAlgorithms/src/RichBasePhotonReco.h @@ -166,18 +166,18 @@ namespace Rich } /// Check the final Cherenkov angles - template < typename HYPODATA > + template < typename HYPODATA, typename FTYPE > inline bool checkAngles( const Rich::RadiatorType rad, const HYPODATA& tkCkAngles, const HYPODATA& tkCkRes, - const float ckTheta, - const float ckPhi ) const noexcept + const FTYPE ckTheta, + const FTYPE ckPhi ) const noexcept { return ( // First the basic checks - ckPhi > 0 && - ckTheta > absMinCKTheta(rad) && ckTheta < absMaxCKTheta(rad) && + ckTheta > absMinCKTheta(rad) && + ckPhi > 0 && // Now check each hypo std::any_of( activeParticles().begin(), activeParticles().end(), -- GitLab