diff --git a/CMakeLists.txt b/CMakeLists.txt index 5dddb66aec32ca29cda9049cc8a48f863a8e1b74..414d95a1b27d4113075e26dbcf87b269e462bcf1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -99,6 +99,7 @@ add_library(DetectorLib SHARED Core/src/MagneticFieldExtension.cpp Detector/LHCb/src/DeLHCb.cpp Detector/LHCb/src/DeLHCbHandles.cpp + Detector/LHCb/src/InteractionRegion.cpp Detector/LHCb/src/Tell40Links.cpp Detector/Rich/src/DeRich.cpp Detector/Rich/src/DeRichRadiator.cpp diff --git a/Core/tests/CMakeLists.txt b/Core/tests/CMakeLists.txt index 8aefa4620d034c18e5c5cb926a77608467f36cd7..432fe90e3bfbbeb571bd19a983795d06593bfe1d 100644 --- a/Core/tests/CMakeLists.txt +++ b/Core/tests/CMakeLists.txt @@ -27,6 +27,7 @@ add_executable(test_DDS src/test_DDS.cpp src/test_DDS_limit_IOV.cpp src/test_DDS_tell40links.cpp + src/test_DDS_interactionregion.cpp ) target_link_libraries(test_DDS Catch2::Catch2WithMain diff --git a/Core/tests/src/test_DDS_interactionregion.cpp b/Core/tests/src/test_DDS_interactionregion.cpp new file mode 100644 index 0000000000000000000000000000000000000000..aa57581068589438c00d82be48a2cea91513dd55 --- /dev/null +++ b/Core/tests/src/test_DDS_interactionregion.cpp @@ -0,0 +1,75 @@ +/*****************************************************************************\ +* (c) Copyright 2022 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. * +\*****************************************************************************/ +#include +#include +#include +#include +#include +#include + +#include + +TEST_CASE( "InteractionRegion loading" ) { + namespace fs = std::filesystem; + using Catch::Matchers::Contains; + + Detector::Test::Fixture f; + + auto& description = f.description(); + + description.fromXML( "compact/trunk/LHCb.xml" ); + + REQUIRE( description.state() == dd4hep::Detector::READY ); + + auto det = description.detector( "/world" ); + // the `!!` is needed because handles have `operator!` but not `operator bool` + REQUIRE( !!det ); + + LHCb::Detector::DetectorDataService dds( description, {"/world"} ); + dds.initialize( nlohmann::json( {{"repository", "file:tests/ConditionsIOV"}} ) ); + + { + // get a condition slice where the condition exists + // - we should get the values from the condition + + auto slice = dds.get_slice( 200 ); + REQUIRE( slice ); + + LHCb::Detector::DeLHCb lhcb = slice->get( det, LHCb::Detector::Keys::deKey ); + REQUIRE( !!lhcb ); + + auto ir = lhcb.interactionRegion(); + REQUIRE( ir.has_value() ); + + CHECK( ir.value().avgPosition == ROOT::Math::XYZPoint{0.0, 0.0, 0.0} ); + CHECK( ir.value().spread.At( 0, 0 ) == 0.0064 ); + CHECK( ir.value().spread.At( 0, 1 ) == 0.0 ); + CHECK( ir.value().spread.At( 0, 2 ) == 0.0 ); + CHECK( ir.value().spread.At( 1, 1 ) == 0.0064 ); + CHECK( ir.value().spread.At( 1, 2 ) == 0.0 ); + CHECK( ir.value().spread.At( 2, 2 ) == 2809.0 ); + CHECK( ir.value().tX() == 0.0 ); + CHECK( ir.value().tY() == 0.0 ); + } + + { + // get a condition slice where the condition doesn't exist + // - we should get the fallback values + auto slice = dds.get_slice( 0 ); + REQUIRE( slice ); + + LHCb::Detector::DeLHCb lhcb = slice->get( det, LHCb::Detector::Keys::deKey ); + REQUIRE( !!lhcb ); + + auto ir = lhcb.interactionRegion(); + REQUIRE( !ir.has_value() ); + } +} diff --git a/Detector/LHCb/include/Detector/LHCb/DeLHCb.h b/Detector/LHCb/include/Detector/LHCb/DeLHCb.h index e5d9c1b7eb5465a0de755dab66d3c38b7c85327d..e942f3ebff31a198d6521e29c635a261bfb1ca1e 100644 --- a/Detector/LHCb/include/Detector/LHCb/DeLHCb.h +++ b/Detector/LHCb/include/Detector/LHCb/DeLHCb.h @@ -13,11 +13,13 @@ #include #include #include +#include #include #include #include +#include namespace LHCb::Detector { @@ -28,6 +30,7 @@ namespace LHCb::Detector { void applyToAllChildren( const std::function )>& ) const override; std::vector children; Tell40Links m_tell40links; + std::optional m_interactionRegion; }; // Utility method to lookup DeIOV object from the condition slice @@ -40,6 +43,9 @@ namespace LHCb::Detector { const Tell40Links& tell40links() const { return access()->m_tell40links; } auto tell40links( Tell40Links::SourceId id ) const { return access()->m_tell40links[id]; } + + /// Provide the position, spread, and tilt of the interaction region + std::optional interactionRegion() const { return this->access()->m_interactionRegion; } }; // Utility method to setup DeLHCb diff --git a/Detector/LHCb/include/Detector/LHCb/InteractionRegion.h b/Detector/LHCb/include/Detector/LHCb/InteractionRegion.h new file mode 100644 index 0000000000000000000000000000000000000000..a498f1b3a68a274171aea01ee206fb7fe31943f7 --- /dev/null +++ b/Detector/LHCb/include/Detector/LHCb/InteractionRegion.h @@ -0,0 +1,31 @@ +/*****************************************************************************\ +* (c) Copyright 2023 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. * +\*****************************************************************************/ +#pragma once + +#include + +#include +#include +#include + +namespace LHCb::Detector { + struct InteractionRegion { + + InteractionRegion() = default; + InteractionRegion( const nlohmann::json& obj ); + + double tX() const { return ( spread( 2, 2 ) != 0.0 ) ? spread( 0, 2 ) / spread( 2, 2 ) : 0.0; } + double tY() const { return ( spread( 2, 2 ) != 0.0 ) ? spread( 1, 2 ) / spread( 2, 2 ) : 0.0; } + + ROOT::Math::XYZPoint avgPosition; + ROOT::Math::SMatrixSym3D spread; + }; +} // namespace LHCb::Detector diff --git a/Detector/LHCb/src/DeLHCb.cpp b/Detector/LHCb/src/DeLHCb.cpp index 8fdd9390c262ffb0d39b86f8b4269073fb59e5e2..1aed64420258e5325c8e955e89415bf29f31974e 100644 --- a/Detector/LHCb/src/DeLHCb.cpp +++ b/Detector/LHCb/src/DeLHCb.cpp @@ -23,6 +23,9 @@ LHCb::Detector::detail::DeLHCbObject::DeLHCbObject( const dd4hep::DetElement& auto links = ctxt.condition( hash_key( de, "Tell40Links" ) ).get(); if ( !links.is_null() ) { m_tell40links = links; } + + auto cond = ctxt.condition( hash_key( de, "InteractionRegion" ) ).get(); + if ( !cond.is_null() ) { m_interactionRegion = cond; } } void LHCb::Detector::detail::DeLHCbObject::applyToAllChildren( @@ -101,5 +104,10 @@ void LHCb::Detector::setup_DeLHCb_callback( dd4hep::Detector& description ) { "Tell40Links" ); depbuilder.add( hash_key( de, "Tell40Links" ) ); + ( *requests ) + ->addLocation( de, LHCb::Detector::item_key( "InteractionRegion" ), + "Conditions/LHCb/Online/InteractionRegion.yml", "InteractionRegion" ); + depbuilder.add( hash_key( de, "InteractionRegion" ) ); + ( *requests )->addDependency( depbuilder.release() ); } diff --git a/Detector/LHCb/src/InteractionRegion.cpp b/Detector/LHCb/src/InteractionRegion.cpp new file mode 100644 index 0000000000000000000000000000000000000000..adf856311b32317446b758de0349284432f88484 --- /dev/null +++ b/Detector/LHCb/src/InteractionRegion.cpp @@ -0,0 +1,55 @@ +/*****************************************************************************\ +* (c) Copyright 2023 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. * +\*****************************************************************************/ +#include + +#include + +#include +#include + +#include + +template +std::array arrayFromJson( const nlohmann::json& jsonArray, const double unit ) { + if ( jsonArray.size() != Size ) { throw std::runtime_error{"InteractionRegion condition array is wrong size"}; } + + std::array values; + + for ( std::size_t i{0}; i < Size; ++i ) { + if ( jsonArray[i].is_string() ) { + values[i] = dd4hep::_toDouble( jsonArray[i].get() ); + } else if ( jsonArray[i].is_number() ) { + values[i] = jsonArray[i].get() * unit; + } else { + throw std::runtime_error{"InteractionRegion condition contains unexpected types"}; + } + } + + return values; +} + +LHCb::Detector::InteractionRegion::InteractionRegion( const nlohmann::json& obj ) { + if ( !obj.contains( "position" ) || !obj.contains( "spread" ) ) { + throw std::runtime_error{"InteractionRegion condition is empty"}; + } + + auto& pos = obj.at( "position" ); + constexpr std::size_t posSize{3}; + std::array posVals{arrayFromJson( pos, dd4hep::mm )}; + + auto& spr = obj.at( "spread" ); + constexpr std::size_t sprSize{6}; + std::array sprVals{arrayFromJson( spr, dd4hep::mm2 )}; + + avgPosition.SetCoordinates( posVals.begin(), posVals.end() ); + + spread.SetElements( sprVals.begin(), sprVals.end(), true ); +} diff --git a/tests/ConditionsIOV/Conditions/LHCb/Online/InteractionRegion.yml/.condition b/tests/ConditionsIOV/Conditions/LHCb/Online/InteractionRegion.yml/.condition new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/tests/ConditionsIOV/Conditions/LHCb/Online/InteractionRegion.yml/0 b/tests/ConditionsIOV/Conditions/LHCb/Online/InteractionRegion.yml/0 new file mode 100644 index 0000000000000000000000000000000000000000..5099ee0e7f00926e829591d693dc9806db8583ba --- /dev/null +++ b/tests/ConditionsIOV/Conditions/LHCb/Online/InteractionRegion.yml/0 @@ -0,0 +1,3 @@ +# Special case of empty condition +--- +InteractionRegion: diff --git a/tests/ConditionsIOV/Conditions/LHCb/Online/InteractionRegion.yml/200 b/tests/ConditionsIOV/Conditions/LHCb/Online/InteractionRegion.yml/200 new file mode 100644 index 0000000000000000000000000000000000000000..0b0cfa96faa2a03a92b58e5e27dc2a25ed21ab5a --- /dev/null +++ b/tests/ConditionsIOV/Conditions/LHCb/Online/InteractionRegion.yml/200 @@ -0,0 +1,10 @@ +# Example of InteractionRegion condition +# ``` +# InteractionRegion: +# position: +# spread: +# ``` +--- +InteractionRegion: + position: [ "0.0*mm", "0.0*mm", "0.0*mm" ] + spread: [ "0.0064*mm2", "0.0*mm2", "0.0064*mm2", "0.0*mm2", "0.0*mm2", "2809.0*mm2" ]