diff --git a/Phys/TrackRefitting/CMakeLists.txt b/Phys/TrackRefitting/CMakeLists.txt index c019f96ee824551216b782d9775e9d89116aa26e..09c8cb554d9ef8905de7cc787c5988763dd8a290 100644 --- a/Phys/TrackRefitting/CMakeLists.txt +++ b/Phys/TrackRefitting/CMakeLists.txt @@ -19,12 +19,14 @@ gaudi_add_module(TrackRefitting src/ReplaceTracksInRecVertex.cpp src/SelectTracksForParticles.cpp src/SelectTracksForRecVertices.cpp + src/UpdateVertexCoordinatesOffline.cpp LINK Gaudi::GaudiAlgLib Gaudi::GaudiKernel LHCb::LHCbAlgsLib LHCb::PhysEvent LHCb::RecEvent + LHCb::LHCbDetLib LHCb::RelationsLib Rec::TrackInterfacesLib Rec::TrackKernel diff --git a/Phys/TrackRefitting/src/UpdateVertexCoordinatesOffline.cpp b/Phys/TrackRefitting/src/UpdateVertexCoordinatesOffline.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0dc413eaa2382b8419c3a11c58e6a4314b2c26d5 --- /dev/null +++ b/Phys/TrackRefitting/src/UpdateVertexCoordinatesOffline.cpp @@ -0,0 +1,151 @@ +/*****************************************************************************\ +* (c) Copyright 2024 CERN for the benefit of the LHCb Collaboration * +* * +* This software is distributed under the terms of the GNU General Public * +* Licence version 3 (GPL Version 3), copied verbatim in the file "COPYING". * +* * +* In applying this licence, CERN does not waive the privileges and immunities * +* granted to it by virtue of its status as an Intergovernmental Organization * +* or submit itself to any jurisdiction. * +\*****************************************************************************/ + +/** + * Uses a dedicated conditon to interpet a primary vertex in an + * 'old' LHCb coordinate system, to a new one. This is useful + * when a the global alignment of the VELO changed. + * + * This algorithm is written purely for PVs, but since it acts + * on general RecVertices, it could be used for other types + * of vertices. + * + * The vertex container returned is a new container, + * which thus takes space on the TES. To help with any + * pre-existing relations, the keys are used as-is from the + * old vertices. + * + * When the special condition is not present, or when running + * on DetDesc, the old container is always returned without any + * change. The return type is a Range of vertices, i.e. non- + * owning container, contrary to the dd4hep case. All downstream + * algorithms are recommended to always take the generic ::Range + * as input, and never require the owning container. + * + * @author Laurent Dufour + */ + +#include "GaudiAlg/GaudiAlgorithm.h" +#include "GaudiKernel/ISvcLocator.h" +#include "GaudiKernel/Transform3DTypes.h" +#include "LHCbAlgs/Transformer.h" + +#include "Event/RecVertex.h" + +#include "DetDesc/DetectorElement.h" +#include "DetDesc/GenericConditionAccessorHolder.h" + +#ifdef USE_DD4HEP +# include "VPDet/DeVP.h" // needed for the path +# include +# include +#endif + +namespace { + using In_t = LHCb::RecVertex::Range; + +#ifdef USE_DD4HEP + using Output_t = LHCb::RecVertices; + + using Transformer_t = + LHCb::Algorithm::Transformer>; + +#else + using Output_t = LHCb::RecVertex::Range; + + // this is a dummy operation, just to keep the control flow in tact + using Transformer_t = LHCb::Algorithm::Transformer; +#endif +} // namespace + +namespace LHCb { + class UpdateVertexCoordinatesOffline final : public Transformer_t { + + private: + mutable Gaudi::Accumulators::Counter<> m_updatedVertices{this, "Updated Vertices"}; + mutable Gaudi::Accumulators::Counter<> m_notUpdatedVertices{this, "Unaltered Vertices"}; + + public: +#ifdef USE_DD4HEP + UpdateVertexCoordinatesOffline( const std::string& name, ISvcLocator* pSvcLocator ) + : Transformer_t( name, pSvcLocator, + {KeyValue{"InputVertices", ""}, KeyValue{"LHCbLocation", LHCb::standard_geometry_top}, + KeyValue { + "VPLocation", + LHCb::Det::VP::det_path + }}, + {KeyValue { + "OutputVertices", + "" + }} ) {} + + Output_t operator()( In_t const& originalPVs, Detector::DeLHCb const& lhcb, + Detector::DeVP const& deVP ) const override { + Output_t outputPVs{}; + outputPVs.reserve( originalPVs.size() ); + + const auto offlineCalib = lhcb.vpGlobalCoordinateTransformation(); + + // deal with the NO UPDATE case first + if ( !offlineCalib || !offlineCalib->enabled ) { + std::for_each( originalPVs.begin(), originalPVs.end(), + [&outputPVs]( const auto& pv ) { outputPVs.insert( pv->clone(), pv->key() ); } ); + + m_notUpdatedVertices += originalPVs.size(); + + return outputPVs; // *clone* the PV container as-is + } + + // example values in 2024: + // {-0.0005157705398491993, 7.011816237252315e-05, -0.00042666842206765687}; + const ROOT::Math::RotationZYX& oldRotation = offlineCalib->oldRotation; + const ROOT::Math::Translation3D& oldTranslation = offlineCalib->oldPosition; + + // example values in 2024: + // {-0.000490856920288708, 7.977795380551605e-05, -0.0008505579346996768}; + const ROOT::Math::RotationZYX& newRotation = deVP.systemRotation(); + const ROOT::Math::Translation3D newTranslation{deVP.systemTranslation()}; + + const auto oldTransMatrix = Gaudi::Transform3D( oldTranslation * oldRotation ); + const auto newTransMatrix = Gaudi::Transform3D( newTranslation * newRotation ); + + for ( const auto& pv : originalPVs ) { + auto newPV = UpdateVertex( *pv, newTransMatrix * oldTransMatrix.Inverse() ); + + outputPVs.insert( newPV.release(), pv->key() ); + } + + m_updatedVertices += outputPVs.size(); + + return outputPVs; + } +#else + UpdateVertexCoordinatesOffline( const std::string& name, ISvcLocator* pSvcLocator ) + : Transformer_t( name, pSvcLocator, {KeyValue{"InputVertices", ""}}, {KeyValue{"OutputVertices", ""}} ) {} + + Output_t operator()( In_t const& originalPVs ) const override { return originalPVs; } +#endif + + private: + std::unique_ptr UpdateVertex( LHCb::RecVertex const& originalPV, + Gaudi::Transform3D const& transformation ) const { + auto newPV = std::make_unique( originalPV ); + + auto position = transformation * newPV->position(); + newPV->setPosition( position ); + + return newPV; + } + }; + + DECLARE_COMPONENT_WITH_ID( UpdateVertexCoordinatesOffline, "UpdateVertexCoordinatesOffline" ) +} // namespace LHCb \ No newline at end of file