Commit eed4969e authored by Christopher Rob Jones's avatar Christopher Rob Jones
Browse files

Merge branch 'lcapriot_ECAL' into 'master'

ECAL&HCAL geometry

See merge request !190
parents 6ffd25bc a81e8b11
Pipeline #4348076 passed with stages
in 13 minutes and 4 seconds
......@@ -73,6 +73,7 @@ add_library(DetectorLib SHARED
Core/src/backtrace.cpp
Core/src/ShapeUtilities.cpp
Detector/Calo/src/DeCaloHandles.cpp
Detector/Calo/src/DeCalorimeter.cpp
Detector/FT/src/DeFT.cpp
Detector/FT/src/DeFTConditionCalls.cpp
Detector/FT/src/DeFTHandles.cpp
......@@ -206,6 +207,10 @@ add_detector_plugin(DetectorPlugins
Detector/Rich2/src/Rich2DEA/Rich2_dump_detelem.cpp
Detector/Rich2/src/Rich2_cond.cpp
Detector/Muon/src/Muon_cond.cpp
Detector/ECAL/src/ECAL_geo.cpp
Detector/ECAL/src/ECAL_cond.cpp
Detector/HCAL/src/HCAL_geo.cpp
Detector/HCAL/src/HCAL_cond.cpp
Detector/Infrastructure/src/BCM_geo.cpp
Detector/Infrastructure/src/BLS_geo.cpp
Detector/Infrastructure/src/DetectorRegion.cpp
......@@ -244,6 +249,7 @@ if(BUILD_TESTING)
add_subdirectory(TestUtils)
# Adding the test subdirectory
add_subdirectory(Core/tests)
add_subdirectory(Detector/Calo/tests)
add_subdirectory(Detector/Muon/tests)
#add_test (NAME MyTest COMMAND Test)
endif()
......
......@@ -25,23 +25,10 @@ add_test(NAME test_GitCondDB
add_test(NAME test_load_all
COMMAND ${TEST_SCRIPT} -input ${PROJECT_SOURCE_DIR}/compact/trunk/LHCb.xml -dry-run)
add_test(NAME test_load_VP_debug
COMMAND ${TEST_SCRIPT} -input ${PROJECT_SOURCE_DIR}/compact/trunk/debug/VP_debug.xml -dry-run)
add_test(NAME test_load_UT_debug
COMMAND ${TEST_SCRIPT} -input ${PROJECT_SOURCE_DIR}/compact/trunk/debug/UT_debug.xml -dry-run)
add_test(NAME test_load_FT_debug
COMMAND ${TEST_SCRIPT} -input ${PROJECT_SOURCE_DIR}/compact/trunk/debug/FT_debug.xml -dry-run)
add_test(NAME test_load_Rich1_debug
COMMAND ${TEST_SCRIPT} -input ${PROJECT_SOURCE_DIR}/compact/trunk/debug/Rich1_debug.xml -dry-run)
add_test(NAME test_load_Rich2_debug
COMMAND ${TEST_SCRIPT} -input ${PROJECT_SOURCE_DIR}/compact/trunk/debug/Rich2_debug.xml -dry-run)
add_test(NAME test_load_Muon_debug
COMMAND ${PROJECT_BINARY_DIR}/bin/run geoPluginRun -input ${PROJECT_SOURCE_DIR}/compact/trunk/debug/Muon_debug.xml -dry-run)
foreach(subdetector IN ITEMS VP UT FT Rich1 Rich2 Muon Ecal Hcal)
add_test(NAME test_load_${subdetector}_debug
COMMAND ${TEST_SCRIPT} -input ${PROJECT_SOURCE_DIR}/compact/trunk/debug/${subdetector}_debug.xml -dry-run)
endforeach()
add_test(NAME test_find_intersection
COMMAND ${TEST_SCRIPT} -input ${PROJECT_SOURCE_DIR}/compact/trunk/LHCb.xml -plugin find_intersections 0 0 0 5 5 5)
......
......@@ -104,7 +104,7 @@ namespace LHCb::Detector::Calo::CellCode {
/// the indices for Calorimeter Detectors (to extract the coding of the "calo" )
enum Index {
Undefined = -1,
// Spd and Prs ar gone
// Spd and Prs are gone
EcalCalo = 2,
HcalCalo,
/// total number of NAMED Calorimeters
......
......@@ -10,18 +10,16 @@
\*****************************************************************************/
#pragma once
#include "Detector/Calo/CaloCardParams.h"
#include "Detector/Calo/CaloCellID.h"
#include "Detector/Calo/CaloLed.h"
#include "Detector/Calo/CaloPin.h"
#include "Detector/Calo/CaloVector.h"
#include "Detector/Calo/CardParam.h"
#include "Detector/Calo/CellParam.h"
#include "Detector/Calo/DeSubCalorimeter.h"
#include "Detector/Calo/Tell1Param.h"
#include "Core/DeIOV.h"
#include <Core/DeIOV.h>
#include <Detector/Calo/CaloCardParams.h>
#include <Detector/Calo/CaloCellID.h>
#include <Detector/Calo/CaloLed.h>
#include <Detector/Calo/CaloPin.h>
#include <Detector/Calo/CaloVector.h>
#include <Detector/Calo/CardParam.h>
#include <Detector/Calo/CellParam.h>
#include <Detector/Calo/DeSubCalorimeter.h>
#include <Detector/Calo/Tell1Param.h>
#include <vector>
namespace LHCb::Detector::Calo {
......@@ -52,6 +50,25 @@ namespace LHCb::Detector::Calo {
struct DeCaloObject : LHCb::Detector::detail::DeIOVObject {
DeCaloObject( dd4hep::DetElement const& de, dd4hep::cond::ConditionUpdateContext& ctxt );
CellCode::Index index{LHCb::Detector::Calo::CellCode::Index::Undefined};
std::string caloName;
double xSize;
double ySize;
double zSize;
double zOffset;
// Hardware parameters (from conditions)
int adcMax;
int centralHoleX;
int centralHoleY;
int maxRowCol;
int firstRowUp;
double centerRowCol;
// Gain parameters (from conditions)
double pedestalShift;
};
} // namespace detail
......@@ -67,14 +84,14 @@ namespace LHCb::Detector::Calo {
using DeIOVElement<ObjectType>::DeIOVElement;
// general
const std::string& caloName() const { throw NotImplemented(); }
const std::string& caloName() const { return this->access()->caloName; }
/// calorimeter index, @see namespace CaloCellCode
CellCode::Index index() const { throw NotImplemented(); }
CellCode::Index index() const { return this->access()->index; }
// accessing the geometry parameters
double xSize() const { throw NotImplemented(); }
double ySize() const { throw NotImplemented(); }
double zSize() const { throw NotImplemented(); }
double zOffset() const { throw NotImplemented(); }
double xSize() const { return this->access()->xSize; }
double ySize() const { return this->access()->ySize; }
double zSize() const { return this->access()->zSize; }
double zOffset() const { return this->access()->zOffset; }
unsigned int numberOfAreas() const { throw NotImplemented(); }
// reference plane in the global frame
inline ROOT::Math::Plane3D plane( const double ) const { throw NotImplemented(); }
......@@ -84,7 +101,7 @@ namespace LHCb::Detector::Calo {
// accessing the calibration parameters
double maxEtInCenter( unsigned int = 0 ) const { throw NotImplemented(); }
double maxEtSlope( unsigned int = 0 ) const { throw NotImplemented(); }
double pedestalShift() const { throw NotImplemented(); }
double pedestalShift() const { return this->access()->pedestalShift; }
double pinPedestalShift() const { throw NotImplemented(); }
double L0EtGain() const { throw NotImplemented(); }
double coherentNoise() const { throw NotImplemented(); }
......@@ -107,7 +124,7 @@ namespace LHCb::Detector::Calo {
double activeToTotal() const { throw NotImplemented(); }
// accessing the hardware parameter(s)
unsigned int adcMax() const { throw NotImplemented(); }
unsigned int adcMax() const { return this->access()->adcMax; }
// accessing the reconstruction parameter(s)
double zShowerMax() const { throw NotImplemented(); }
......
/*****************************************************************************\
* (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 <Core/Keys.h>
#include <Detector/Calo/DeCalorimeter.h>
#include <yaml-cpp/yaml.h>
using namespace LHCb::Detector::Calo;
using LHCb::Detector::hash_key;
detail::DeCaloObject::DeCaloObject( dd4hep::DetElement const& de, dd4hep::cond::ConditionUpdateContext& ctxt )
: DeIOVObject( de, ctxt ), index( CellCode::caloNum( de.name() ) ), caloName( std::string( de.name() ) + "Det" ) {
// get the dimensions from the geometry
dd4hep::Box box = de.solid();
if ( !box ) throw std::runtime_error( std::string( de.name() ) + " shape is not a box" );
xSize = 2. * box.x();
ySize = 2. * box.y();
// these were defined in the DDDB XML of the detectors
if ( index == CellCode::Index::EcalCalo ) {
zOffset = dd4hep::_toDouble( "-0.5 * EcalMidModLength + 0.5 * EcalStackLength + EcalMidFrontCoverLength" );
zSize = dd4hep::_toDouble( "EcalStackLength" );
} else if ( index == CellCode::Index::HcalCalo ) {
zOffset = dd4hep::_toDouble( "-0.5 * HcalTotSpace + HcalFwFaceLength + 3 * HcalMsPlStepLength" );
zSize = dd4hep::_toDouble( "6 * HcalMsPlStepLength" );
} else {
throw std::runtime_error( std::string( "DeCalorimeter does not support detector " ) + de.name() );
}
auto hardware = ctxt.condition( hash_key( de, "Hardware" ), true ).get<YAML::Node>();
adcMax = hardware["AdcMax"].as<int>();
auto coding = hardware["CodingBit"].as<int>();
maxRowCol = ( 1 << coding ) - 1; // 63 (31 for HCAL)
firstRowUp = maxRowCol / 2 + 1; // 32 (16 for HCAL)
centerRowCol = .5 * static_cast<double>( maxRowCol ); // 31.5 (15.5 for HCAL)
centralHoleX = hardware["centralHoleX"].as<int>();
centralHoleY = hardware["centralHoleY"].as<int>();
auto gain = ctxt.condition( hash_key( de, "Gain" ), true ).get<YAML::Node>();
pedestalShift = gain["PedShift"].as<double>();
}
###############################################################################
# (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. #
###############################################################################
add_executable(test_DeCalorimeter src/test_DeCalorimeter.cpp)
target_link_libraries(test_DeCalorimeter Catch2::Catch2 DetectorLib)
# FIXME: this is too specific to the way lcg-toolchains and Gaudi projects work
set_target_properties(test_DeCalorimeter PROPERTIES CROSSCOMPILING_EMULATOR ${PROJECT_BINARY_DIR}/bin/run)
# This is to ensure that we have everything we need if we want to build and run only test_DeCalorimeter
add_dependencies(test_DeCalorimeter DetectorPlugins)
catch_discover_tests(test_DeCalorimeter
TEST_PREFIX Detector.Calo.
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
PROPERTIES
LABELS "Detector"
LABELS "Detector.Calo"
)
/*****************************************************************************\
* (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 <Core/DetectorDataService.h>
#include <Core/Keys.h>
#include <DD4hep/Detector.h>
#include <DD4hep/Printout.h>
#include <Detector/Calo/DeCalorimeter.h>
#include <TError.h> // gErrorIgnoreLevel
#define CATCH_CONFIG_MAIN // This tells Catch to provide a main()
#include <catch2/catch.hpp>
TEST_CASE( "Ecal" ) {
// turn off DD4hep printouts
std::cout << "Lets start" << std::endl;
dd4hep::setPrintLevel( static_cast<dd4hep::PrintLevel>( dd4hep::ALWAYS + 1 ) );
// turn off ROOT printouts
gErrorIgnoreLevel = kError + 1;
dd4hep::Detector& description = dd4hep::Detector::getInstance();
description.fromXML( "compact/trunk/debug/Ecal_debug.xml" );
std::cout << "got xml" << std::endl;
REQUIRE( description.state() == dd4hep::Detector::READY );
auto ecal = description.detector( "Ecal" );
// the `!!` is needed because handles have `operator!` but not `operator bool`
REQUIRE( !!ecal );
std::cout << "loading conditions" << std::endl;
// load conditions
LHCb::Detector::DetectorDataService dds( description, {"/world", "Ecal"} );
dds.initialize( "file:tests/ConditionsIOV", "" );
auto slice = dds.get_slice( 100 );
REQUIRE( slice );
std::cout << "conditions loaded" << std::endl;
using namespace LHCb::Detector::Calo;
DeCalorimeter de = slice->get( ecal, LHCb::Detector::Keys::deKey );
REQUIRE( !!de );
std::cout << "DeCalo loaded" << std::endl;
CHECK( de.caloName() == "EcalDet" );
CHECK( de.index() == CellCode::Index::EcalCalo );
CHECK( de.xSize() == 64. * ( 121.7 + 2 * 0.1 ) * dd4hep::mm ); // from XML
CHECK( de.ySize() == dd4hep::_toDouble( "EcalYSize" ) );
CHECK( de.zSize() == 432. * dd4hep::mm );
CHECK( std::abs( de.zOffset() - ( -113.5 * dd4hep::mm ) ) < 1.e-6 );
CHECK( de.adcMax() == 4095 ); // from YAML
CHECK( de.access()->maxRowCol == 63 ); // from YAML
CHECK( de.access()->firstRowUp == 32 );
CHECK( de.access()->centerRowCol == 31.5 );
CHECK( de.access()->centralHoleX == 8 ); // from YAML
CHECK( de.access()->centralHoleY == 6 ); // from YAML
CHECK( de.pedestalShift() == 0.4 ); // from test/ConditionsIOV
std::cout << "all checks done" << std::endl;
dd4hep::Detector::destroyInstance();
std::cout << "destroy instance" << std::endl;
}
TEST_CASE( "Hcal" ) {
// turn off DD4hep printouts
dd4hep::setPrintLevel( static_cast<dd4hep::PrintLevel>( dd4hep::ALWAYS + 1 ) );
// turn off ROOT printouts
gErrorIgnoreLevel = kError + 1;
dd4hep::Detector& description = dd4hep::Detector::getInstance();
description.fromXML( "compact/trunk/debug/Hcal_debug.xml" );
REQUIRE( description.state() == dd4hep::Detector::READY );
auto hcal = description.detector( "Hcal" );
// the `!!` is needed because handles have `operator!` but not `operator bool`
REQUIRE( !!hcal );
// load conditions
LHCb::Detector::DetectorDataService dds( description, {"/world", "Hcal"} );
dds.initialize( "file:tests/ConditionsIOV", "" );
auto slice = dds.get_slice( 100 );
REQUIRE( slice );
using namespace LHCb::Detector::Calo;
DeCalorimeter de = slice->get( hcal, LHCb::Detector::Keys::deKey );
REQUIRE( !!de );
CHECK( de.caloName() == "HcalDet" );
CHECK( de.index() == CellCode::Index::HcalCalo );
CHECK( de.xSize() == 2. * 8. * 2. * 262.6 * dd4hep::mm ); // from XML
CHECK( de.ySize() == dd4hep::_toDouble( "HcalTotYSize" ) );
CHECK( de.zSize() == 1200. * dd4hep::mm );
CHECK( std::abs( de.zOffset() - ( -213.5 * dd4hep::mm ) ) < 1.e-6 );
CHECK( de.adcMax() == 4095 ); // from YAML
CHECK( de.access()->maxRowCol == 31 ); // from YAML
CHECK( de.access()->firstRowUp == 16 );
CHECK( de.access()->centerRowCol == 15.5 );
CHECK( de.access()->centralHoleX == 2 ); // from YAML
CHECK( de.access()->centralHoleY == 2 ); // from YAML
CHECK( de.pedestalShift() == 0.4 ); // from test/ConditionsIOV
dd4hep::Detector::destroyInstance();
}
/*****************************************************************************\
* (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 <Core/ConditionHelper.h>
#include <Core/DeConditionCall.h>
#include <DD4hep/ConditionDerived.h>
#include <DD4hep/DetElement.h>
#include <DD4hep/Detector.h>
#include <DD4hep/Printout.h>
#include <Detector/Calo/DeCalorimeter.h>
#include <yaml-cpp/yaml.h>
namespace {
struct EcalConditionCall : LHCb::Detector::DeConditionCall {
using DeConditionCall::DeConditionCall;
virtual dd4hep::Condition operator()( const dd4hep::ConditionKey& key,
dd4hep::cond::ConditionUpdateContext& context ) override final {
using namespace LHCb::Detector;
if ( key.item_key() == Keys::deKey ) {
// This is the pointer we need to return at the end of the callback
auto det = dd4hep::Detector::getInstance().detector( "Ecal" );
auto deobj = new Calo::detail::DeCaloObject( det, context );
return DeIOV( deobj );
}
throw std::logic_error( "Key unknown to EcalConditionCall" );
}
};
} // namespace
// DD4hep plugin to parse the Magnet_cond.xml and set up the conditions
static long create_conditions_recipes( dd4hep::Detector& description, xml_h e ) {
// Use the helper to load the XML, setup the callback according
LHCb::Detector::ConditionConfigHelper<EcalConditionCall> config_helper{description, "Ecal", e};
config_helper.configure();
return 1;
}
DECLARE_XML_DOC_READER( LHCb_Ecal_cond, create_conditions_recipes )
This diff is collapsed.
/*****************************************************************************\
* (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 <Core/ConditionHelper.h>
#include <Core/DeConditionCall.h>
#include <DD4hep/ConditionDerived.h>
#include <DD4hep/DetElement.h>
#include <DD4hep/Detector.h>
#include <DD4hep/Printout.h>
#include <Detector/Calo/DeCalorimeter.h>
#include <yaml-cpp/yaml.h>
namespace {
struct HcalConditionCall : LHCb::Detector::DeConditionCall {
using DeConditionCall::DeConditionCall;
virtual dd4hep::Condition operator()( const dd4hep::ConditionKey& key,
dd4hep::cond::ConditionUpdateContext& context ) override final {
using namespace LHCb::Detector;
if ( key.item_key() == Keys::deKey ) {
// This is the pointer we need to return at the end of the callback
auto det = dd4hep::Detector::getInstance().detector( "Hcal" );
auto deobj = new Calo::detail::DeCaloObject( det, context );
return DeIOV( deobj );
}
throw std::logic_error( "Key unknown to HcalConditionCall" );
}
};
} // namespace
// DD4hep plugin to parse the Magnet_cond.xml and set up the conditions
static long create_conditions_recipes( dd4hep::Detector& description, xml_h e ) {
// Use the helper to load the XML, setup the callback according
LHCb::Detector::ConditionConfigHelper<HcalConditionCall> config_helper{description, "Hcal", e};
config_helper.configure();
return 1;
}
DECLARE_XML_DOC_READER( LHCb_Hcal_cond, create_conditions_recipes )
This diff is collapsed.
......@@ -150,4 +150,99 @@
<composite n="3" ref="O" />
</material>
<!-- ***************************************************************************
Update with ECAL and HCAL specific materials
Adapted from EcalMaterials.xml and HcalMaterials.xml
2022/06/21 12:30:07 lcapriot
******************************************************************************** -->
<!-- ### Ecal&Hcal Stack Lead ### -->
<material formula="CaloPb" name="Calo Lead" state="solid" >
<RL type="X0" unit="cm" value="0.56" />
<NIL type="lambda" unit="cm" value="17.63" /> <!-- Fixed from slightly wrong value in Runs 1-2 -->
<D type="density" unit="g/cm3" value="11.35" />
<composite n="1.0" ref="Pb" />
</material>
<!-- ### Ecal&Hcal Scintillator: Polystyrene (C6H5CH=CH2) ### -->
<material formula="CaloSc" name="Calo scintillator" state="solid" >
<RL type="X0" unit="cm" value="42.4" />
<NIL type="lambda" unit="cm" value="79.46" />
<D type="density" unit="g/cm3" value="1.032" />
<composite n="8" ref="H" />
<composite n="8" ref="C" />
</material>
<!-- ### Ecal Stack Plastic: Polystyrene (C6H5CH=CH2) ### -->
<material formula="EcalPlastic" name="Ecal plastic" state="solid" >
<RL type="X0" unit="cm" value="42.4" />
<NIL type="lambda" unit="cm" value="79.46" />
<D type="density" unit="g/cm3" value="1.032" />
<composite n="8" ref="H" />
<composite n="8" ref="C" />
</material>
<!-- ### Ecal Stack Fiber: Polystyrene (C6H5CH=CH2) ### -->
<material formula="EcalFiber" name="Ecal fiber" state="solid" >
<RL type="X0" unit="cm" value="42.4" />
<NIL type="lambda" unit="cm" value="79.46" />
<D type="density" unit="g/cm3" value="1.032" />
<composite n="8" ref="H" />
<composite n="8" ref="C" />
</material>
<!-- ### Ecal&Hcal Steel ### -->
<material formula="CaloSteel" name="Calo steel" state="solid" >
<D type="density" unit="g/cm3" value="7.87" />
<fraction n="0.97" ref="Fe" />
<fraction n="0.03" ref="C" />
</material>
<!-- ### Ecal Paper: TYVEK ### -->
<material formula="EcalPaper" name="Ecal paper" state="solid" >
<D type="density" unit="g/cm3" value="2.265" />
<fraction n="1.0" ref="C" />
</material>
<!-- ### Ecal Plastic for Outer Module Front Cover ### -->
<material formula="EcalPlasticOutFC" name="Ecal plastic out FC" state="solid" >
<D type="density" unit="g/cm3" value="0.235" />
<fraction n="0.996" ref="Ecal plastic" />
<fraction n="0.004" ref="Air" />
</material>
<!-- ### Ecal Plastic for Middle Module Front Cover ### -->
<material formula="EcalPlasticMidFC" name="Ecal plastic mid FC" state="solid" >
<D type="density" unit="g/cm3" value="0.254" />
<fraction n="0.9964" ref="Ecal plastic" />
<fraction n="0.0036" ref="Air" />
</material>
<!-- ### Ecal Plastic for Inner Module Front Cover ### -->
<material formula="EcalPlasticInnFC" name="Ecal plastic inn FC" state="solid" >
<D type="density" unit="g/cm3" value="0.287" />
<fraction n="0.9968" ref="Ecal plastic" />
<fraction n="0.0032" ref="Air" />
</material>
<!-- ### Ecal Plastic for all Modules Back Cover ### -->
<material formula="EcalPlasticBC" name="Ecal plastic BC" state="solid" >
<D type="density" unit="g/cm3" value="0.110" />
<fraction n="0.999" ref="Ecal plastic" />
<fraction n="0.001" ref="Air" />
</material>
<!-- ### Ecal DrilledAluminium for Shield ### -->
<material formula="EcalDrilledAluminium" name="Ecal drilled aluminium" state="solid" >
<D type="density" unit="g/cm3" value="1.35060" />
<fraction n="0.99955" ref="Al" />
<fraction n="0.00045" ref="Air" />
</material>
</materials>
<!--
(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.
-->
<lccdd>
<plugins>
<plugin name="LHCb_Ecal_cond_XML_reader" type="xml">
<conditions_config prefix="Conditions/Ecal"/>
<alignment detector="Ecal" path="Alignment.yml" name="EcalSystem"/>
<conditions path="Calibration.yml">
<condition name="Calibration"/>
<condition name="Gain"/>
<condition name="L0Calibration"/>
<condition name="LEDReference"/>
<condition name="PileUpOffset"/>
<condition name="Quality"/>