diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 4e9c688312e4180f48f5f64f0ac341345ac41f9e..9de6be441a32f781e3d62222f2c6134e0dc3bb78 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -38,7 +38,7 @@ test_unittest: tags: - k8s-cvmfs script: - - set +e && export ALRB_CONT_RUNPAYLOAD="asetup --input=asetup.faser Athena,24.0.41; source `find . -name 'setup.sh'`; cd build; ctest -j3 --output-on-failure" && set -e + - set +e && export ALRB_CONT_RUNPAYLOAD="asetup --input=asetup.faser Athena,24.0.41; source `find . -name 'setup.sh'`; cd build; ctest -j3" && set -e - echo $ALRB_CONT_RUNPAYLOAD - set +e && source ${ATLAS_LOCAL_ROOT_BASE}/user/atlasLocalSetup.sh -c alma9 && set -e dependencies: diff --git a/Calorimeter/CaloDetDescr/CaloIdDictFiles/data/IdDictCalorimeter.xml b/Calorimeter/CaloDetDescr/CaloIdDictFiles/data/IdDictCalorimeter.xml index 37bed2379f814331055b953646980bbd9e3b444e..8e8b3bb5fb98e203fa5da7a5eeecd67b70ea3b65 100644 --- a/Calorimeter/CaloDetDescr/CaloIdDictFiles/data/IdDictCalorimeter.xml +++ b/Calorimeter/CaloDetDescr/CaloIdDictFiles/data/IdDictCalorimeter.xml @@ -1,7 +1,8 @@ <IdDictionary name="Calorimeter"> <field name="part" > - <label name="Ecal" value="1" /> + <label name="Ecal" value="1" /> + <label name="CaloNu" value="2" /> </field> <field name="row"> @@ -23,4 +24,12 @@ <range field="module" values="Starboard Port" wraparound="FALSE" /> <range field="pmt" minvalue="0" maxvalue="1" /> </region> + + <region> + <range field="part" value="CaloNu" /> + <range field="row" values="Bottom Top" wraparound="FALSE" /> + <range field="module" values="Starboard Port" wraparound="FALSE" /> + <range field="pmt" minvalue="0" maxvalue="0" /> + </region> + </IdDictionary> diff --git a/Calorimeter/CaloDetDescr/CaloIdDictFiles/data/IdDictCalorimeter_TB00.xml b/Calorimeter/CaloDetDescr/CaloIdDictFiles/data/IdDictCalorimeter_TB00.xml index c932a0c74bfeaf9d15648d49eb6a2cfa5aeb49b8..6099442785b80501ab30124b558de98f467f8fb8 100644 --- a/Calorimeter/CaloDetDescr/CaloIdDictFiles/data/IdDictCalorimeter_TB00.xml +++ b/Calorimeter/CaloDetDescr/CaloIdDictFiles/data/IdDictCalorimeter_TB00.xml @@ -2,6 +2,7 @@ <field name="part" > <label name="Ecal" value="1" /> + <label name="CaloNu" value="2" /> </field> <field name="row"> @@ -24,4 +25,4 @@ <range field="module" values="Starboard Center Port" wraparound="FALSE" /> <range field="pmt" minvalue="0" maxvalue="0" /> </region> -</IdDictionary> \ No newline at end of file +</IdDictionary> diff --git a/Calorimeter/CaloDetDescr/FaserCaloIdentifier/CMakeLists.txt b/Calorimeter/CaloDetDescr/FaserCaloIdentifier/CMakeLists.txt index 54ba749cddc246185bc3d2e161bb56663f0a925c..497b2e92d0672e8d60a4ba19c8d9e8c6740957c8 100644 --- a/Calorimeter/CaloDetDescr/FaserCaloIdentifier/CMakeLists.txt +++ b/Calorimeter/CaloDetDescr/FaserCaloIdentifier/CMakeLists.txt @@ -11,6 +11,7 @@ find_package( ROOT COMPONENTS Core Tree MathCore Hist RIO pthread ) # Component(s) in the package: atlas_add_library( FaserCaloIdentifier src/EcalID.cxx + src/CaloNuID.cxx PUBLIC_HEADERS FaserCaloIdentifier PRIVATE_INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} LINK_LIBRARIES AthenaKernel FaserDetDescr IdDict Identifier diff --git a/Calorimeter/CaloDetDescr/FaserCaloIdentifier/FaserCaloIdentifier/CaloNuID.h b/Calorimeter/CaloDetDescr/FaserCaloIdentifier/FaserCaloIdentifier/CaloNuID.h new file mode 100644 index 0000000000000000000000000000000000000000..f3fa83d7b846b06cbd45c78805c9060ac110baa8 --- /dev/null +++ b/Calorimeter/CaloDetDescr/FaserCaloIdentifier/FaserCaloIdentifier/CaloNuID.h @@ -0,0 +1,540 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef CALOIDENTIFIER_CALONUID_H +#define CALOIDENTIFIER_CALONUID_H +/** + * @file CaloNuID.h + * + * @brief This is an Identifier helper class for the CaloNu + * subdetector. This class is a factory for creating compact + * Identifier objects and IdentifierHash or hash ids. And it also + * allows decoding of these ids. + * + */ + +//<<<<<< INCLUDES >>>>>> + +#include "FaserDetDescr/FaserDetectorID.h" +#include "Identifier/Identifier.h" +#include "Identifier/IdentifierHash.h" +#include "Identifier/Range.h" +#include "Identifier/IdHelper.h" +#include "IdDict/IdDictFieldImplementation.h" +#include "AthenaKernel/CLASS_DEF.h" + +#include <string> +#include <assert.h> +#include <algorithm> + +//<<<<<< PUBLIC DEFINES >>>>>> +//<<<<<< PUBLIC CONSTANTS >>>>>> +//<<<<<< PUBLIC TYPES >>>>>> + +class IdDictDictionary; + +//<<<<<< PUBLIC VARIABLES >>>>>> +//<<<<<< PUBLIC FUNCTIONS >>>>>> +//<<<<<< CLASS DECLARATIONS >>>>>> + +/** + ** @class CaloNuID + ** + ** @brief This is an Identifier helper class for the CaloNu + ** subdetector. This class is a factory for creating compact + ** Identifier objects and IdentifierHash or hash ids. And it also + ** allows decoding of these ids. + ** + ** Definition and the range of values for the levels of the + ** identifier are: + ** + ** @verbatim + ** element range meaning + ** ------- ----- ------- + ** + ** row 0 - 1 vertical location of module (bottom, top) + ** module 0 - 1 horizontal location of module in row (left, right) + ** pmt 0 single pmt per module + ** + ** @endverbatim + ** + */ +class CaloNuID : public FaserDetectorID +{ +public: + + /// @name public typedefs + //@{ + typedef Identifier::size_type size_type; + typedef std::vector<Identifier>::const_iterator const_id_iterator; + typedef MultiRange::const_identifier_factory const_expanded_id_iterator; + //@} + + /// @name strutors + //@{ + CaloNuID(void); + virtual ~CaloNuID(void) = default; + //@} + + /// @name Creators for module ids and pmt ids + //@{ + /// For a single row + Identifier row_id ( int row ) const; + Identifier row_id ( int row, + bool checks) const; + + /// For a row from a module id + Identifier row_id ( const Identifier& module_id ) const; + + /// For a single module + Identifier module_id ( int row, + int module ) const; + Identifier module_id ( int row, + int module, + bool checks) const; + + /// For a single module from a pmt id + Identifier module_id ( const Identifier& pmt_id ) const; + + /// From hash - optimized + Identifier module_id ( IdentifierHash module_hash ) const; + + /// For an individual pmt + Identifier pmt_id ( int row, + int module, + int pmt ) const; + + Identifier pmt_id ( int row, + int module, + int pmt, + bool check ) const; + + Identifier pmt_id ( const Identifier& module_id, + int pmt ) const; + + //@} + + + /// @name Hash table maximum sizes + //@{ + size_type module_hash_max (void) const; + size_type pmt_hash_max (void) const; + //@} + + /// @name Access to all ids + //@{ + /// Iterators over full set of ids. Module iterator is sorted + const_id_iterator module_begin (void) const; + const_id_iterator module_end (void) const; + /// For pmt ids, only expanded id iterators are available. Use + /// following "pmt_id" method to obtain a compact identifier + const_expanded_id_iterator pmt_begin (void) const; + const_expanded_id_iterator pmt_end (void) const; + //@} + + + /// @name Optimized accessors - ASSUMES id IS an CaloNu id, i.e. NOT other + //@{ + /// module hash from id - optimized + IdentifierHash module_hash (Identifier module_id) const; + + /// Values of different levels (failure returns 0) + int row (const Identifier& id) const; + int module (const Identifier& id) const; + int pmt (const Identifier& id) const; + + /// Max/Min values for each field (-999 == failure) + int row_max (const Identifier& id) const; + int module_max (const Identifier& id) const; + int pmt_max (const Identifier& id) const; + //@} + + /// @name module navigation + //@{ + // /// Previous in z + // int get_prev_in_z(const IdentifierHash& id, IdentifierHash& prev) const; + // /// Next in z + // int get_next_in_z(const IdentifierHash& id, IdentifierHash& next) const; + /// Previous module hash in phi (return == 0 for neighbor found) + int get_prev_in_phi (const IdentifierHash& id, IdentifierHash& prev) const; + /// Next module hash in phi (return == 0 for neighbor found) + int get_next_in_phi (const IdentifierHash& id, IdentifierHash& next) const; + /// Previous module hash in eta (return == 0 for neighbor found) + int get_prev_in_eta (const IdentifierHash& id, IdentifierHash& prev) const; + // /// Next module hash in eta (return == 0 for neighbor found) + int get_next_in_eta (const IdentifierHash& id, IdentifierHash& next) const; + // /// Wafer hash on other side + // int get_other_side (const IdentifierHash& id, IdentifierHash& other) const; + + // Check limits + bool is_phi_module_max(const Identifier& id) const; + bool is_phi_module_min(const Identifier& id) const; + bool is_eta_module_min(const Identifier& id) const; + bool is_eta_module_max(const Identifier& id) const; + //@} + + /// @name contexts to distinguish module id from pmt id + //@{ + IdContext module_context (void) const; + IdContext pmt_context (void) const; + //@} + + /// @name methods from abstract interface - slower than opt version + //@{ + /// Create compact id from hash id (return == 0 for OK) + virtual int get_id (const IdentifierHash& hash_id, + Identifier& id, + const IdContext* context = 0) const; + + /// Create hash id from compact id (return == 0 for OK) + virtual int get_hash (const Identifier& id, + IdentifierHash& hash_id, + const IdContext* context = 0) const; + //@} + + /// Return the lowest bit position used in the channel id + int base_bit (void) const; + + /// Calculate a channel offset between the two identifiers. + Identifier::diff_type calc_offset(const Identifier& base, + const Identifier& target) const; + + /// Create an identifier with a given base and channel offset + Identifier pmt_id_offset(const Identifier& base, + Identifier::diff_type offset) const; + + /// @name interaction with id dictionary + //@{ + /// Create strip Identifier from expanded id, which is returned by the + /// id_iterators + Identifier pmt_id (const ExpandedIdentifier& pmt_id) const; + + /// Create expanded id from compact id (return == 0 for OK) + void get_expanded_id (const Identifier& id, + ExpandedIdentifier& exp_id, + const IdContext* context = 0) const; + + /// Initialization from the identifier dictionary + virtual int initialize_from_dictionary(const IdDictMgr& dict_mgr); + + /// Tests of packing + void test_module_packing (void) const; + //@} + +private: + + enum {NOT_VALID_HASH = 64000}; + + typedef std::vector<Identifier> id_vec; + typedef id_vec::const_iterator id_vec_it; + typedef std::vector<unsigned short> hash_vec; + typedef hash_vec::const_iterator hash_vec_it; + + void module_id_checks ( int row, + int module ) const; + + void pmt_id_checks ( int row, + int module, + int pmt ) const; + + + int initLevelsFromDict(void); + + int init_hashes(void); + + int init_neighbors(void); + + // Temporary method for adapting an identifier for the MultiRange + // check - MR is missing the InnerDetector level + // Identifier idForCheck (const Identifier& id) const; + + size_type m_calonu_region_index; + size_type m_CALO_INDEX; + size_type m_CALONU_INDEX; + size_type m_ROW_INDEX; + size_type m_MODULE_INDEX; + size_type m_PMT_INDEX; + + const IdDictDictionary* m_dict; + MultiRange m_full_module_range; + MultiRange m_full_pmt_range; + size_type m_module_hash_max; + size_type m_pmt_hash_max; + // Range::field m_barrel_field; + id_vec m_module_vec; + // hash_vec m_prev_z_plate_vec; + // hash_vec m_next_z_plate_vec; + hash_vec m_prev_phi_module_vec; + hash_vec m_next_phi_module_vec; + hash_vec m_prev_eta_module_vec; + hash_vec m_next_eta_module_vec; + // bool m_hasRows ; + + IdDictFieldImplementation m_calo_impl ; + IdDictFieldImplementation m_calonu_impl ; + IdDictFieldImplementation m_row_impl ; + IdDictFieldImplementation m_module_impl ; + IdDictFieldImplementation m_pmt_impl ; +}; + + +//<<<<<< INLINE PUBLIC FUNCTIONS >>>>>> + +///////////////////////////////////////////////////////////////////////////// +//<<<<<< INLINE MEMBER FUNCTIONS >>>>>> +///////////////////////////////////////////////////////////////////////////// + +//using the macros below we can assign an identifier (and a version) +//This is required and checked at compile time when you try to record/retrieve +CLASS_DEF(CaloNuID, 167327975, 1) + +//---------------------------------------------------------------------------- +inline Identifier +CaloNuID::row_id ( int row, + bool checks) const +{ + + // Build identifier + Identifier result((Identifier::value_type)0); + + // Pack fields independently + m_calo_impl.pack (calo_field_value(), result); + m_calonu_impl.pack (calonu_field_value(), result); + m_row_impl.pack (row, result); + // Do checks + if(checks) + { + module_id_checks ( row, 0 ); + } + + return result; +} + +inline Identifier +CaloNuID::row_id ( int row ) const +{ + return row_id (row, do_checks()); +} + +//---------------------------------------------------------------------------- +inline Identifier +CaloNuID::row_id ( const Identifier& module_id ) const +{ + Identifier result(module_id); + // Reset the module and pmt fields + m_module_impl.reset(result); + m_pmt_impl.reset(result); + return (result); +} + +//---------------------------------------------------------------------------- +inline Identifier +CaloNuID::module_id ( int row, + int module, + bool checks) const +{ + // Build identifier + Identifier result((Identifier::value_type)0); + + // Pack fields independently + m_calo_impl.pack (calo_field_value(), result); + m_calonu_impl.pack (calonu_field_value(), result); + m_row_impl.pack (row, result); + m_module_impl.pack (module, result); + + // Do checks + if(checks) + { + module_id_checks ( row, module ); + } + return result; +} + +inline Identifier +CaloNuID::module_id ( int row, + int module ) const +{ + return module_id (row, module, do_checks()); +} + +//---------------------------------------------------------------------------- +inline Identifier +CaloNuID::module_id ( const Identifier& pmt_id ) const +{ + Identifier result(pmt_id); + // reset the pmt field + m_pmt_impl.reset(result); + return (result); +} + +//---------------------------------------------------------------------------- +inline Identifier CaloNuID::module_id ( IdentifierHash module_hash ) const +{ + return (m_module_vec[module_hash]); +} + +//---------------------------------------------------------------------------- +inline IdentifierHash CaloNuID::module_hash (Identifier module_id) const +{ + // MsgStream log(m_msgSvc, "CaloNuID"); + // log << MSG::VERBOSE << "m_module_vec size: " << m_module_vec.size() << endmsg; + // log << MSG::VERBOSE << "input id = " << module_id << endmsg; + // for (size_t i = 0; i < m_module_vec.size(); i++) + // { + // log << MSG::VERBOSE << "Hash = " << i << " : ID = " << m_module_vec[i] << endmsg; + // } + id_vec_it it = std::lower_bound(m_module_vec.begin(), + m_module_vec.end(), + module_id); + // Require that module_id matches the one in vector + if (it != m_module_vec.end() && module_id == (*it)) { + return (it - m_module_vec.begin()); + } + IdentifierHash result; + return (result); // return hash in invalid state +} + +//---------------------------------------------------------------------------- +inline Identifier +CaloNuID::pmt_id ( int row, + int module, + int pmt, + bool checks) const +{ + // Build identifier + Identifier result((Identifier::value_type)0); + + // Pack fields independently + m_calo_impl.pack (calo_field_value(), result); + m_calonu_impl.pack (calonu_field_value(), result); + m_row_impl.pack (row, result); + m_module_impl.pack (module, result); + m_pmt_impl.pack (pmt, result); + + // Do checks + if(checks) { + pmt_id_checks ( row, module, pmt ); + } + return result; +} + +inline Identifier +CaloNuID::pmt_id ( int row, + int module, + int pmt ) const +{ + return pmt_id (row, module, pmt, do_checks()); +} + +//---------------------------------------------------------------------------- +inline Identifier +CaloNuID::pmt_id (const ExpandedIdentifier& id) const +{ + // Build identifier + Identifier result((Identifier::value_type)0); + + // Pack fields independently + m_calo_impl.pack (calo_field_value(), result); + m_calonu_impl.pack (calonu_field_value(), result); + m_row_impl.pack (id[m_ROW_INDEX], result); + m_module_impl.pack (id[m_MODULE_INDEX], result); + m_pmt_impl.pack (id[m_PMT_INDEX], result); + + // Do checks + if(m_do_checks) + { + pmt_id_checks ( id[m_ROW_INDEX], + id[m_MODULE_INDEX], + id[m_PMT_INDEX]); + } + return result; +} + +//---------------------------------------------------------------------------- +inline Identifier +CaloNuID::pmt_id ( const Identifier& module_id, int pmt ) const +{ + // Build identifier + Identifier result(module_id); + + // Reset pmt and then add in value + m_pmt_impl.reset (result); + m_pmt_impl.pack (pmt, result); + + if(m_do_checks) + { + pmt_id_checks ( row(result), + module(result), + pmt ); + } + return result; +} + +//---------------------------------------------------------------------------- +inline Identifier::diff_type +CaloNuID::calc_offset(const Identifier& base, const Identifier& target) const +{ + Identifier::diff_type tval = static_cast<Identifier::diff_type>(target.get_compact() >> base_bit()); + Identifier::diff_type bval = static_cast<Identifier::diff_type>(base.get_compact() >> base_bit()); + return (tval - bval); +} + +//---------------------------------------------------------------------------- +inline Identifier +CaloNuID::pmt_id_offset(const Identifier& base, + Identifier::diff_type offset) const +{ + Identifier::value_type bval = base.get_compact() >> base_bit(); + return Identifier((bval + offset) << base_bit()); +} + +//---------------------------------------------------------------------------- +inline int +CaloNuID::base_bit ( void ) const +{ + int base = static_cast<int>(m_pmt_impl.shift()); // lowest field base + return (base > 32) ? 32 : base; + // max base is 32 so we can still read old strip id's and differences + // from non-SLHC releases. +} + +//---------------------------------------------------------------------------- +inline IdContext +CaloNuID::module_context (void) const +{ + ExpandedIdentifier id; + return (IdContext(id, 0, m_MODULE_INDEX)); +} + +//---------------------------------------------------------------------------- +inline IdContext +CaloNuID::pmt_context (void) const +{ + ExpandedIdentifier id; + return (IdContext(id, 0, m_PMT_INDEX)); +} + +//---------------------------------------------------------------------------- +inline int +CaloNuID::row (const Identifier& id) const +{ + return (m_row_impl.unpack(id)); +} + +//---------------------------------------------------------------------------- +inline int +CaloNuID::module (const Identifier& id) const +{ + return (m_module_impl.unpack(id)); +} + +//---------------------------------------------------------------------------- +inline int +CaloNuID::pmt (const Identifier& id) const +{ + return (m_pmt_impl.unpack(id)); +} + + +#endif // CALOIDENTIFIER_CALONUID_H diff --git a/Calorimeter/CaloDetDescr/FaserCaloIdentifier/FaserCaloIdentifier/FaserCaloIdentifierDict.h b/Calorimeter/CaloDetDescr/FaserCaloIdentifier/FaserCaloIdentifier/FaserCaloIdentifierDict.h index 2d8825f50fa3aec58ad56e3a4bd161774a429714..42b8c1655692e8d116c7acf46e840695d026e506 100644 --- a/Calorimeter/CaloDetDescr/FaserCaloIdentifier/FaserCaloIdentifier/FaserCaloIdentifierDict.h +++ b/Calorimeter/CaloDetDescr/FaserCaloIdentifier/FaserCaloIdentifier/FaserCaloIdentifierDict.h @@ -13,5 +13,6 @@ #define FASERCALOIDENTIFIER_CALOIDENTIFIERDICT_H #include "FaserCaloIdentifier/EcalID.h" +#include "FaserCaloIdentifier/CaloNuID.h" #endif // FASERCALOIDENTIFIER_CALOIDENTIFIERDICT_H diff --git a/Calorimeter/CaloDetDescr/FaserCaloIdentifier/FaserCaloIdentifier/selection.xml b/Calorimeter/CaloDetDescr/FaserCaloIdentifier/FaserCaloIdentifier/selection.xml index d66c6ce0e07e175229e53c2dd8e4554e1f5d55cd..6b475bbc17b1be6fd0e8f7084a0d887dfe20e4f4 100644 --- a/Calorimeter/CaloDetDescr/FaserCaloIdentifier/FaserCaloIdentifier/selection.xml +++ b/Calorimeter/CaloDetDescr/FaserCaloIdentifier/FaserCaloIdentifier/selection.xml @@ -1,3 +1,4 @@ <lcgdict> <class name="EcalID" /> + <class name="CaloNuID" /> </lcgdict> diff --git a/Calorimeter/CaloDetDescr/FaserCaloIdentifier/src/CaloNuID.cxx b/Calorimeter/CaloDetDescr/FaserCaloIdentifier/src/CaloNuID.cxx new file mode 100644 index 0000000000000000000000000000000000000000..586c006d98a7f292f1dabef96de5dbcc06e233c8 --- /dev/null +++ b/Calorimeter/CaloDetDescr/FaserCaloIdentifier/src/CaloNuID.cxx @@ -0,0 +1,865 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +/*************************************************************************** + Calorimeter identifier package + ------------------------------------------- +***************************************************************************/ + +//<<<<<< INCLUDES >>>>>> +#include "GaudiKernel/MsgStream.h" + +#include "FaserCaloIdentifier/CaloNuID.h" +#include "Identifier/IdentifierHash.h" +#include "IdDict/IdDictDefs.h" +#include <set> +#include <algorithm> +#include <iostream> + +//<<<<<< PRIVATE DEFINES >>>>>> +//<<<<<< PRIVATE CONSTANTS >>>>>> +//<<<<<< PRIVATE TYPES >>>>>> +//<<<<<< PRIVATE VARIABLE DEFINITIONS >>>>>> +//<<<<<< PUBLIC VARIABLE DEFINITIONS >>>>>> +//<<<<<< CLASS STRUCTURE INITIALIZATION >>>>>> +//<<<<<< PRIVATE FUNCTION DEFINITIONS >>>>>> +//<<<<<< PUBLIC FUNCTION DEFINITIONS >>>>>> +//<<<<<< MEMBER FUNCTION DEFINITIONS >>>>>> + + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + + +CaloNuID::CaloNuID(void) + : + m_calonu_region_index(0), + m_CALO_INDEX(0), + m_CALONU_INDEX(1), + m_ROW_INDEX(2), + m_MODULE_INDEX(3), + m_PMT_INDEX(4), + m_dict(0), + m_module_hash_max(0), + m_pmt_hash_max(0) +{ +} + +void +CaloNuID::module_id_checks ( int row, + int module ) const +{ + + // Check that id is within allowed range + + // Fill expanded id + ExpandedIdentifier id; + id << calo_field_value() << calonu_field_value() + << row << module; + + if (!m_full_module_range.match(id)) { // module range check is sufficient + MsgStream log(m_msgSvc, "CaloNuID"); + log << MSG::ERROR << " CaloNuID::module_id result is NOT ok. ID, range " + << (std::string)id << " " << (std::string)m_full_module_range << endmsg; + } +} + +void +CaloNuID::pmt_id_checks ( int row, + int module, + int pmt) const +{ + + // Check that id is within allowed range + + // Fill expanded id + ExpandedIdentifier id; + id << calo_field_value() << calonu_field_value() + << row << module << pmt; + + if (!m_full_pmt_range.match(id)) { + MsgStream log(m_msgSvc, "CaloNuID"); + log << MSG::ERROR << " CaloNuID::pmt_id result is NOT ok. ID, range " + << (std::string)id << " " << (std::string)m_full_pmt_range << std::endl; + } +} + +int +CaloNuID::row_max(const Identifier& id) const +{ + // get max from dictionary + ExpandedIdentifier expId; + IdContext module_context1 = module_context(); + get_expanded_id(id, expId, &module_context1); + for (unsigned int i = 0; i < m_full_module_range.size(); ++i) { + const Range& range = m_full_module_range[i]; + if (range.match(expId)) { + const Range::field& row_field = range[m_ROW_INDEX]; + if (row_field.has_maximum()) { + return (row_field.get_maximum()); + } + } + } + return (-999); // default +} + +int +CaloNuID::pmt_max (const Identifier& id) const +{ + ExpandedIdentifier expId; + IdContext row_context(expId, 0, m_ROW_INDEX); + get_expanded_id(id, expId, &row_context); + int result = -999; + for (unsigned int i = 0; i < m_full_pmt_range.size(); ++i) { + const Range& range = m_full_pmt_range[i]; + if (range.match(expId)) { + const Range::field& pmt_field = range[m_PMT_INDEX]; + if (pmt_field.has_maximum()) { + int pmt = pmt_field.get_maximum(); + if (result < pmt) result = pmt; + } + } + } + return (result); +} + +int +CaloNuID::module_max(const Identifier& id) const +{ + // get max from dictionary + ExpandedIdentifier expId; + IdContext module_context1 = module_context(); + get_expanded_id(id, expId, &module_context1); + for (unsigned int i = 0; i < m_full_module_range.size(); ++i) { + const Range& range = m_full_module_range[i]; + if (range.match(expId)) { + const Range::field& module_field = range[m_MODULE_INDEX]; + if (module_field.has_maximum()) { + return (module_field.get_maximum()); + } + } + } + return -1; +} + +int +CaloNuID::initialize_from_dictionary(const IdDictMgr& dict_mgr) +{ + MsgStream log(m_msgSvc, "CaloNuID"); + log << MSG::INFO << "Initialize from dictionary" << endmsg; + + // Check whether this helper should be reinitialized + if (!reinitialize(dict_mgr)) { + log << MSG::INFO << "Request to reinitialize not satisfied - tags have not changed" << endmsg; + return (0); + } + else { + if (m_msgSvc) { + log << MSG::DEBUG << "(Re)initialize" << endmsg; + } + else { + std::cout << " DEBUG (Re)initialize" << std::endl; + } + } + + // init base object + if(FaserDetectorID::initialize_from_dictionary(dict_mgr)) return (1); + + // Register version of InnerDetector dictionary + if (register_dict_tag(dict_mgr, "Calorimeter")) return(1); + + m_dict = dict_mgr.find_dictionary ("Calorimeter"); + if(!m_dict) { + log << MSG::ERROR << " CaloNuID::initialize_from_dict - cannot access Calorimeter dictionary " << endmsg; + return 1; + } + + // Initialize the field indices + if(initLevelsFromDict()) return (1); + + // + // Build multirange for the valid set of identifiers + // + + + // Find value for the field Scintillator + const IdDictDictionary* faserDict = dict_mgr.find_dictionary ("FASER"); + int caloField = -1; + if (faserDict->get_label_value("subdet", "Calorimeter", caloField)) { + log << MSG::ERROR << "Could not get value for label 'Calorimeter' of field 'subdet' in dictionary " + << faserDict->m_name + << endmsg; + return (1); + } + + // Find value for the field CaloNu + int calonuField = -1; + if (m_dict->get_label_value("part", "CaloNu", calonuField)) { + log << MSG::ERROR << "Could not get value for label 'CaloNu' of field 'part' in dictionary " + << m_dict->m_name + << endmsg; + return (1); + } + if (m_msgSvc) { + log << MSG::DEBUG << " CaloNuID::initialize_from_dict " + << "Found field values: CaloNu " + << calonuField + << std::endl; + } + else { + std::cout << " DEBUG CaloNuID::initialize_from_dict " + << "Found field values: CaloNu " + << calonuField + << std::endl; + } + + // Set up id for region and range prefix + ExpandedIdentifier region_id; + region_id.add(caloField); + region_id.add(calonuField); + Range prefix; + m_full_module_range = m_dict->build_multirange(region_id, prefix, "module"); + m_full_pmt_range = m_dict->build_multirange(region_id, prefix); + + // Setup the hash tables + if(init_hashes()) return (1); + + // Setup hash tables for finding neighbors + if(init_neighbors()) return (1); + + if (m_msgSvc) { + log << MSG::INFO << " CaloNuID::initialize_from_dict " << endmsg; + log << MSG::DEBUG + << "Module range -> " << (std::string)m_full_module_range + << endmsg; + log << MSG::DEBUG + << "Pmt range -> " << (std::string)m_full_pmt_range + << endmsg; + } + else { + std::cout << " INFO CaloNuID::initialize_from_dict " << std::endl; + std::cout << " DEBUG Module range -> " << (std::string)m_full_module_range + << std::endl; + std::cout << " DEBUG Pmt range -> " << (std::string)m_full_pmt_range + << std::endl; + } + + return 0; +} + +int +CaloNuID::init_hashes(void) +{ + + // + // create a vector(s) to retrieve the hashes for compact ids. For + // the moment, we implement a hash for modules but NOT for pmts + // + MsgStream log(m_msgSvc, "CaloNuID"); + // module hash + m_module_hash_max = m_full_module_range.cardinality(); + m_module_vec.resize(m_module_hash_max); + unsigned int nids = 0; + std::set<Identifier> ids; + for (unsigned int i = 0; i < m_full_module_range.size(); ++i) { + const Range& range = m_full_module_range[i]; + Range::const_identifier_factory first = range.factory_begin(); + Range::const_identifier_factory last = range.factory_end(); + for (; first != last; ++first) { + const ExpandedIdentifier& exp_id = (*first); + Identifier id = module_id(exp_id[m_ROW_INDEX], + exp_id[m_MODULE_INDEX]); + if(!(ids.insert(id)).second) { + log << MSG::ERROR << " CaloNuID::init_hashes " + << " Error: duplicated id for module id. nid " << nids + << " compact id " << id.getString() + << " id " << (std::string)exp_id << endmsg; + return (1); + } + nids++; + } + } + if(ids.size() != m_module_hash_max) { + log << MSG::ERROR << " CaloNuID::init_hashes " + << " Error: set size NOT EQUAL to hash max. size " << ids.size() + << " hash max " << m_module_hash_max + << endmsg; + return (1); + } + + nids = 0; + std::set<Identifier>::const_iterator first = ids.begin(); + std::set<Identifier>::const_iterator last = ids.end(); + for (; first != last && nids < m_module_vec.size(); ++first) { + m_module_vec[nids] = (*first); + nids++; + } + + // pmt hash - we do not keep a vec for the pmts + m_pmt_hash_max = m_full_pmt_range.cardinality(); + + return (0); +} + + // int + // CaloNuID::get_prev_in_z(const IdentifierHash& id, IdentifierHash& prev) const + // { + // unsigned short index = id; + // if (index < m_prev_z_module_vec.size()) + // { + // if (m_prev_z_module_vec[index] == NOT_VALID_HASH) return (1); + // prev = m_prev_z_module_vec[index]; + // return (0); + // } + // return (1); + // } + + // int + // CaloNuID::get_next_in_z(const IdentifierHash& id, IdentifierHash& next) const + // { + // unsigned short index = id; + // if (index < m_next_z_module_vec.size()) + // { + // if (m_next_z_module_vec[index] == NOT_VALID_HASH) return (1); + // next = m_next_z_module_vec[index]; + // return (0); + // } + // return (1); + // } + +int +CaloNuID::get_prev_in_phi(const IdentifierHash& id, IdentifierHash& prev) const +{ + unsigned short index = id; + if (index < m_prev_phi_module_vec.size()) { + if (m_prev_phi_module_vec[index] == NOT_VALID_HASH) return (1); + prev = m_prev_phi_module_vec[index]; + return (0); + } + return (1); +} + +int +CaloNuID::get_next_in_phi(const IdentifierHash& id, IdentifierHash& next) const +{ + unsigned short index = id; + if (index < m_next_phi_module_vec.size()) { + if (m_next_phi_module_vec[index] == NOT_VALID_HASH) return (1); + next = m_next_phi_module_vec[index]; + return (0); + } + return (1); +} + +int +CaloNuID::get_prev_in_eta(const IdentifierHash& id, IdentifierHash& prev) const +{ + unsigned short index = id; + if (index < m_prev_eta_module_vec.size()) { + if (m_prev_eta_module_vec[index] == NOT_VALID_HASH) return (1); + prev = m_prev_eta_module_vec[index]; + return (0); + } + return (1); +} + +int +CaloNuID::get_next_in_eta(const IdentifierHash& id, IdentifierHash& next) const +{ + unsigned short index = id; + if (index < m_next_eta_module_vec.size()) { + if (m_next_eta_module_vec[index] == NOT_VALID_HASH) return (1); + next = m_next_eta_module_vec[index]; + return (0); + } + return (1); +} + +int +CaloNuID::init_neighbors(void) +{ + // + // create a vector(s) to retrieve the hashes for compact ids for + // module neighbors. + // + MsgStream log(m_msgSvc, "CaloNuID"); + + m_prev_phi_module_vec.resize(m_module_hash_max, NOT_VALID_HASH); + m_next_phi_module_vec.resize(m_module_hash_max, NOT_VALID_HASH); + m_prev_eta_module_vec.resize(m_module_hash_max, NOT_VALID_HASH); + m_next_eta_module_vec.resize(m_module_hash_max, NOT_VALID_HASH); + + for (unsigned int i = 0; i < m_full_module_range.size(); ++i) { + const Range& range = m_full_module_range[i]; + const Range::field& phi_field = range[m_MODULE_INDEX]; + const Range::field& eta_field = range[m_ROW_INDEX]; + Range::const_identifier_factory first = range.factory_begin(); + Range::const_identifier_factory last = range.factory_end(); + for (; first != last; ++first) { + const ExpandedIdentifier& exp_id = (*first); + ExpandedIdentifier::element_type previous_phi; + ExpandedIdentifier::element_type next_phi; + ExpandedIdentifier::element_type previous_eta; + ExpandedIdentifier::element_type next_eta; + bool pphi = phi_field.get_previous(exp_id[m_MODULE_INDEX], previous_phi); + bool nphi = phi_field.get_next (exp_id[m_MODULE_INDEX], next_phi); + bool peta = eta_field.get_previous(exp_id[m_ROW_INDEX], previous_eta); + bool neta = eta_field.get_next (exp_id[m_ROW_INDEX], next_eta); + + IdContext wcontext = module_context(); + + // First get primary hash id + IdentifierHash hash_id; + Identifier id = module_id(exp_id[m_ROW_INDEX], + exp_id[m_MODULE_INDEX]); + if (get_hash(id, hash_id, &wcontext)) { + log << MSG::ERROR << " CaloNuID::init_neighbors - unable to get hash, exp/compact " + << show_to_string(id, &wcontext) + << " " << (std::string)m_full_module_range << endmsg; + return (1); + } + + // index for the subsequent arrays + unsigned short index = hash_id; + assert (hash_id < m_prev_phi_module_vec.size()); + assert (hash_id < m_next_phi_module_vec.size()); + assert (hash_id < m_prev_eta_module_vec.size()); + assert (hash_id < m_next_eta_module_vec.size()); + + if (pphi) { + // Get previous phi hash id + ExpandedIdentifier expId = exp_id; + expId[m_MODULE_INDEX] = previous_phi; + Identifier id = module_id(expId[m_ROW_INDEX], + expId[m_MODULE_INDEX]); + if (get_hash(id, hash_id, &wcontext)) { + log << MSG::ERROR << " CaloNuID::init_neighbors - unable to get previous phi hash, exp/compact " << id.getString() << " " + << endmsg; + return (1); + } + m_prev_phi_module_vec[index] = hash_id; + } + + if (nphi) { + // Get next phi hash id + ExpandedIdentifier expId = exp_id; + expId[m_MODULE_INDEX] = next_phi; + Identifier id = module_id(expId[m_ROW_INDEX], + expId[m_MODULE_INDEX]); + if (get_hash(id, hash_id, &wcontext)) { + log << MSG::ERROR << " CaloNuID::init_neighbors - unable to get next phi hash, exp/compact " << id.getString() << + " " << MSG::hex << id.getString() << MSG::dec << endmsg; + return (1); + } + m_next_phi_module_vec[index] = hash_id; + } + + if (peta) { + // Get previous eta hash id + ExpandedIdentifier expId = exp_id; + expId[m_ROW_INDEX] = previous_eta; + Identifier id = module_id(expId[m_ROW_INDEX], + expId[m_MODULE_INDEX]); + if (get_hash(id, hash_id, &wcontext)) { + log << MSG::ERROR << " CaloNuID::init_neighbors - unable to get previous eta hash, exp/compact " << id.getString() + << " " << std::endl; + return (1); + } + m_prev_eta_module_vec[index] = hash_id; + } + + if (neta) { + // Get next eta hash id + ExpandedIdentifier expId = exp_id; + expId[m_ROW_INDEX] = next_eta; + Identifier id = module_id(expId[m_ROW_INDEX], + expId[m_MODULE_INDEX]); + if (get_hash(id, hash_id, &wcontext)) { + log << MSG::ERROR << " CaloNuID::init_neighbors - unable to get next eta hash, exp/compact " << id.getString() + << " " << endmsg; + return (1); + } + m_next_eta_module_vec[index] = hash_id; + } + + + // std::cout << " CaloNuID::init_neighbors " + // << " phi, previous, next " << id[m_MODULE_INDEX] + // << " " << pphi + // << " " << previous_phi + // << " " << nphi + // << " " << next_phi + // << " eta, previous, next " << id[m_ROW_INDEX] + // << " " << peta + // << " " << previous_eta + // << " " << neta + // << " " << next_eta + // << " id " << (std::string)(*first) + // << std::endl; + } + } + return (0); +} + + + +int +CaloNuID::initLevelsFromDict() +{ + MsgStream log(m_msgSvc, "CaloNuID"); + if(!m_dict) { + log << MSG::ERROR << " CaloNuID::initLevelsFromDict - dictionary NOT initialized " << endmsg; + return (1); + } + + // Find out which identifier field corresponds to each level. Use + // names to find each field/leve. + + m_CALO_INDEX = 999; + m_CALONU_INDEX = 999; + m_ROW_INDEX = 999; + m_MODULE_INDEX = 999; + m_PMT_INDEX = 999; + + // Save index to a CaloNu region for unpacking + ExpandedIdentifier id; + id << calo_field_value() << calonu_field_value(); + if (m_dict->find_region(id, m_calonu_region_index)) { + log << MSG::ERROR << "CaloNuID::initLevelsFromDict - unable to find calonu region index: id, reg " + << (std::string)id << " " << m_calonu_region_index + << endmsg; + return (1); + } + + // Find a CaloNu region + IdDictField* field = m_dict->find_field("subdet"); + if (field) { + m_CALO_INDEX = field->m_index; + } + else { + log << MSG::ERROR << "CaloNuID::initLevelsFromDict - unable to find 'subdet' field " << endmsg; + return (1); + } + field = m_dict->find_field("part"); + if (field) { + m_CALONU_INDEX = field->m_index; + } + else { + log << MSG::ERROR << "CaloNuID::initLevelsFromDict - unable to find 'part' field " << endmsg; + return (1); + } + field = m_dict->find_field("row"); + if (field) { + m_ROW_INDEX = field->m_index; + } + else { + log << MSG::ERROR << "CaloNuID::initLevelsFromDict - unable to find 'row' field " << endmsg; + return (1); + } + field = m_dict->find_field("module"); + if (field) { + m_MODULE_INDEX = field->m_index; + } + else { + log << MSG::ERROR<< "CaloNuID::initLevelsFromDict - unable to find 'module' field " << endmsg; + return (1); + } + field = m_dict->find_field("pmt"); + if (field) { + m_PMT_INDEX = field->m_index; + } + else { + log << MSG::ERROR << "CaloNuID::initLevelsFromDict - unable to find 'pmt' field " << endmsg; + return (1); + } + + // Set the field implementations + + const IdDictRegion& region = *m_dict->m_regions[m_calonu_region_index]; + + m_calo_impl = region.m_implementation[m_CALO_INDEX]; + m_calonu_impl = region.m_implementation[m_CALONU_INDEX]; + m_row_impl = region.m_implementation[m_ROW_INDEX]; + m_module_impl = region.m_implementation[m_MODULE_INDEX]; + m_pmt_impl = region.m_implementation[m_PMT_INDEX]; + + if (m_msgSvc) { + log << MSG::DEBUG << "decode index and bit fields for each level: " << endmsg; + log << MSG::DEBUG << "calo " << m_calo_impl.show_to_string() << endmsg; + log << MSG::DEBUG << "calonu " << m_calonu_impl.show_to_string() << endmsg; + log << MSG::DEBUG << "row " << m_row_impl.show_to_string() << endmsg; + log << MSG::DEBUG << "module " << m_module_impl.show_to_string() << endmsg; + log << MSG::DEBUG << "pmt " << m_pmt_impl.show_to_string() << endmsg; + } + else { + std::cout << " DEBUG decode index and bit fields for each level: " << std::endl; + std::cout << " DEBUG calo " << m_calo_impl.show_to_string() << std::endl; + std::cout << " DEBUG calonu " << m_calonu_impl.show_to_string() << std::endl; + std::cout << " DEBUG row " << m_row_impl.show_to_string() << std::endl; + std::cout << " DEBUG module " << m_module_impl.show_to_string() << std::endl; + std::cout << " DEBUG pmt " << m_pmt_impl.show_to_string() << std::endl; + } + + std::cout << "calo " << m_calo_impl.decode_index() << " " + << (std::string)m_calo_impl.ored_field() << " " + << std::hex << m_calo_impl.mask() << " " + << m_calo_impl.zeroing_mask() << " " + << std::dec << m_calo_impl.shift() << " " + << m_calo_impl.bits() << " " + << m_calo_impl.bits_offset() + << std::endl; + std::cout << "calonu " << m_calonu_impl.decode_index() << " " + << (std::string)m_calonu_impl.ored_field() << " " + << std::hex << m_calonu_impl.mask() << " " + << m_calonu_impl.zeroing_mask() << " " + << std::dec << m_calonu_impl.shift() << " " + << m_calonu_impl.bits() << " " + << m_calonu_impl.bits_offset() + << std::endl; + std::cout << "row "<< m_row_impl.decode_index() << " " + << (std::string)m_row_impl.ored_field() << " " + << std::hex << m_row_impl.mask() << " " + << m_row_impl.zeroing_mask() << " " + << std::dec << m_row_impl.shift() << " " + << m_row_impl.bits() << " " + << m_row_impl.bits_offset() + << std::endl; + std::cout << "module " << m_module_impl.decode_index() << " " + << (std::string)m_module_impl.ored_field() << " " + << std::hex << m_module_impl.mask() << " " + << m_module_impl.zeroing_mask() << " " + << std::dec << m_module_impl.shift() << " " + << m_module_impl.bits() << " " + << m_module_impl.bits_offset() + << std::endl; + std::cout << "pmt" << m_pmt_impl.decode_index() << " " + << (std::string)m_pmt_impl.ored_field() << " " + << std::hex << m_pmt_impl.mask() << " " + << m_pmt_impl.zeroing_mask() << " " + << std::dec << m_pmt_impl.shift() << " " + << m_pmt_impl.bits() << " " + << m_pmt_impl.bits_offset() + << std::endl; + + return (0); +} + +CaloNuID::size_type +CaloNuID::module_hash_max (void) const +{ + return m_module_hash_max; +} + +CaloNuID::size_type +CaloNuID::pmt_hash_max (void) const +{ + return m_pmt_hash_max; +} + +CaloNuID::const_id_iterator CaloNuID::module_begin (void) const +{ + return (m_module_vec.begin()); +} + +CaloNuID::const_id_iterator CaloNuID::module_end (void) const +{ + return (m_module_vec.end()); +} + +CaloNuID::const_expanded_id_iterator CaloNuID::pmt_begin (void) const +{ + return (m_full_pmt_range.factory_begin()); +} + +CaloNuID::const_expanded_id_iterator CaloNuID::pmt_end (void) const +{ + return (m_full_pmt_range.factory_end()); +} + +// From hash get Identifier +int +CaloNuID::get_id (const IdentifierHash& hash_id, + Identifier& id, + const IdContext* context) const +{ + + int result = 1; + id.clear(); + + size_t begin = (context) ? context->begin_index(): 0; + // cannot get hash if end is 0: + size_t end = (context) ? context->end_index() : 0; + if (0 == begin) { + // No hashes yet for ids with prefixes + if (m_MODULE_INDEX == end) { + if (hash_id < (unsigned int)(m_module_vec.end() - m_module_vec.begin())) { + id = m_module_vec[hash_id]; + result = 0; + } + } + else if (m_PMT_INDEX == end) { + // Do not know how to calculate strip id from hash yet!! + std::cout << "Do not know how to calculate pmt id from hash yet!!" << std::endl; + } + } + return (result); +} + +void +CaloNuID::get_expanded_id (const Identifier& id, + ExpandedIdentifier& exp_id, + const IdContext* context) const +{ + exp_id.clear(); + exp_id << calo_field_value() + << calonu_field_value() + << row(id) + << module(id); + if(!context || context->end_index() == m_PMT_INDEX) + { + exp_id << pmt(id); + } +} + +int +CaloNuID::get_hash (const Identifier& id, + IdentifierHash& hash_id, + const IdContext* context) const +{ + + // Get the hash code from either a vec (for module) or calculate + // it (pmts). For the former, we convert to compact and call + // get_hash again. For the latter, we calculate the hash from the + // Identifier. + + int result = 1; + hash_id = 0; + size_t begin = (context) ? context->begin_index(): 0; + size_t end = (context) ? context->end_index() : 0; + if (0 == begin) { + // No hashes yet for ids with prefixes + if (m_MODULE_INDEX == end) { + hash_id = module_hash(id); + if (hash_id.is_valid()) result = 0; + } + else if (context && context->end_index() == m_PMT_INDEX) { + // Must calculate for pmt hash + ExpandedIdentifier new_id; + get_expanded_id(id, new_id); + hash_id = m_full_pmt_range.cardinalityUpTo(new_id); + result = 0; + } + } + return (result); +} + + +void +CaloNuID::test_module_packing (void) const +{ + MsgStream log(m_msgSvc, "CaloNuID"); + + if (m_dict) { + + int nids = 0; + int nerr = 0; + IdContext context = module_context(); + const_id_iterator first = m_module_vec.begin(); + const_id_iterator last = m_module_vec.end(); + for (; first != last; ++first, ++nids) { + Identifier id = (*first); + ExpandedIdentifier exp_id; + get_expanded_id(id, exp_id, &context); + Identifier new_id = module_id(exp_id[m_ROW_INDEX], + exp_id[m_MODULE_INDEX]); + if (id != new_id) { + log << MSG::ERROR << "CaloNuID::test_module_packing: new and old compacts not equal. New/old/expanded ids " + << MSG::hex << show_to_string(id) << " " << show_to_string(new_id) << " " << MSG::dec + << (std::string)exp_id << endmsg; + nerr++; + continue; + } + // check row id + if (!exp_id[m_MODULE_INDEX]) { + + Identifier new_id1 = row_id(exp_id[m_ROW_INDEX]); + if (id != new_id1) { + log << MSG::ERROR << "CaloNuID::test_module_packing: new and old row ids not equal. New/old/expanded ids " + << MSG::hex << show_to_string(id) << " " << show_to_string(new_id1) << " " << MSG::dec + << (std::string)exp_id << endmsg; + nerr++; + continue; + } + } + } + + if (m_msgSvc) { + log << MSG::DEBUG << "CaloNuID::test_module_packing: tested module and row ids. nids, errors " + << nids << " " << nerr << endmsg; + } + else { + std::cout << " DEBUG CaloNuID::test_module_packing: tested module and row ids. nids, errors " + << nids << " " << nerr << std::endl; + } + + nids = 0; + context = pmt_context(); + const_expanded_id_iterator first_calonu = pmt_begin(); + const_expanded_id_iterator last_calonu = pmt_end(); + for (; first_calonu != last_calonu; ++first_calonu, ++nids) { + // if (nids%10000 != 1) continue; + const ExpandedIdentifier& exp_id = *first_calonu; + ExpandedIdentifier new_exp_id; + + Identifier id = module_id(exp_id[m_ROW_INDEX], + exp_id[m_MODULE_INDEX]); + get_expanded_id(id, new_exp_id, &context); + if (exp_id[0] != new_exp_id[0] || + exp_id[1] != new_exp_id[1] || + exp_id[2] != new_exp_id[2] || + exp_id[3] != new_exp_id[3]) + { + log << MSG::ERROR << "CaloNuID::test_module_packing: new and old ids not equal. New/old/compact ids " + << (std::string)new_exp_id << " " << (std::string)exp_id + << " " << show_to_string(id) << endmsg; + continue; + } + + Identifier pmtid ; + Identifier pmtid1 ; + pmtid = pmt_id ( + exp_id[m_ROW_INDEX], + exp_id[m_MODULE_INDEX], + exp_id[m_PMT_INDEX]); + + pmtid1 = pmt_id ( + row(pmtid), + module(pmtid), + pmt(pmtid)); + + if (pmtid != pmtid1) { + log << MSG::ERROR << "CaloNuID::test_module_packing: new and old pmt ids not equal. New/old ids " + << " " << show_to_string(pmtid1) << " " + << show_to_string(pmtid) << endmsg; + } + } + + if (m_msgSvc) { + log << MSG::DEBUG << "CaloNuID::test_module_packing: Successful tested " + << nids << " ids. " + << endmsg; + } + else { + std::cout << " DEBUG CaloNuID::test_module_packing: Successful tested " + << nids << " ids. " + << std::endl; + } + } + else { + log << MSG::ERROR << "CaloNuID::test_module_packing: Unable to test module packing - no dictionary has been defined. " + << endmsg; + } +} + diff --git a/Calorimeter/CaloDetDescrCnv/CaloIdCnv/src/CaloIdCnv_entries.cxx b/Calorimeter/CaloDetDescrCnv/CaloIdCnv/src/CaloIdCnv_entries.cxx index 46971794e0241e93a06eb6defd6c01607f3e7c3b..768522f42732cbdf0189c29adc97994ce2f220ad 100644 --- a/Calorimeter/CaloDetDescrCnv/CaloIdCnv/src/CaloIdCnv_entries.cxx +++ b/Calorimeter/CaloDetDescrCnv/CaloIdCnv/src/CaloIdCnv_entries.cxx @@ -1,4 +1,6 @@ #include "EcalIDDetDescrCnv.h" +#include "CaloNuIDDetDescrCnv.h" DECLARE_CONVERTER(EcalIDDetDescrCnv) +DECLARE_CONVERTER(CaloNuIDDetDescrCnv) diff --git a/Calorimeter/CaloDetDescrCnv/CaloIdCnv/src/CaloNuIDDetDescrCnv.cxx b/Calorimeter/CaloDetDescrCnv/CaloIdCnv/src/CaloNuIDDetDescrCnv.cxx new file mode 100644 index 0000000000000000000000000000000000000000..ec589bfc0f9eef9418682fe5dd5b519161a7ebf1 --- /dev/null +++ b/Calorimeter/CaloDetDescrCnv/CaloIdCnv/src/CaloNuIDDetDescrCnv.cxx @@ -0,0 +1,239 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +/*************************************************************************** + Calo DetDescrCnv package + ----------------------------------------- + ***************************************************************************/ + +//<<<<<< INCLUDES >>>>>> + +#include "CaloNuIDDetDescrCnv.h" + +#include "DetDescrCnvSvc/DetDescrConverter.h" +#include "DetDescrCnvSvc/DetDescrAddress.h" +#include "GaudiKernel/MsgStream.h" +#include "StoreGate/StoreGateSvc.h" + +#include "IdDictDetDescr/IdDictManager.h" +#include "FaserCaloIdentifier/CaloNuID.h" + + +//<<<<<< PRIVATE DEFINES >>>>>> +//<<<<<< PRIVATE CONSTANTS >>>>>> +//<<<<<< PRIVATE TYPES >>>>>> +//<<<<<< PRIVATE VARIABLE DEFINITIONS >>>>>> +//<<<<<< PUBLIC VARIABLE DEFINITIONS >>>>>> +//<<<<<< CLASS STRUCTURE INITIALIZATION >>>>>> +//<<<<<< PRIVATE FUNCTION DEFINITIONS >>>>>> +//<<<<<< PUBLIC FUNCTION DEFINITIONS >>>>>> +//<<<<<< MEMBER FUNCTION DEFINITIONS >>>>>> + +//-------------------------------------------------------------------- + +long int +CaloNuIDDetDescrCnv::repSvcType() const +{ + return (storageType()); +} + +//-------------------------------------------------------------------- + +StatusCode +CaloNuIDDetDescrCnv::initialize() +{ + // First call parent init + StatusCode sc = DetDescrConverter::initialize(); + MsgStream log(msgSvc(), "CaloNuIDDetDescrCnv"); + log << MSG::DEBUG << "in initialize" << endmsg; + + if (sc.isFailure()) { + log << MSG::ERROR << "DetDescrConverter::initialize failed" << endmsg; + return sc; + } + + // The following is an attempt to "bootstrap" the loading of a + // proxy for CaloNuID into the detector store. However, + // CaloNuIDDetDescrCnv::initialize is NOT called by the conversion + // service. So for the moment, this cannot be use. Instead the + // DetDescrCnvSvc must do the bootstrap from a parameter list. + + +// // Add Calo_DetDescrManager proxy as entry point to the detector store +// // - this is ONLY needed for the manager of each system +// sc = addToDetStore(classID(), "CaloNuID"); +// if (sc.isFailure()) { +// log << MSG::FATAL << "Unable to add proxy for CaloNuID to the Detector Store!" << endmsg; +// return StatusCode::FAILURE; +// } else {} + + return StatusCode::SUCCESS; +} + +//-------------------------------------------------------------------- + +StatusCode +CaloNuIDDetDescrCnv::finalize() +{ + MsgStream log(msgSvc(), "CaloNuIDDetDescrCnv"); + log << MSG::DEBUG << "in finalize" << endmsg; + + return StatusCode::SUCCESS; +} + +//-------------------------------------------------------------------- + +StatusCode +CaloNuIDDetDescrCnv::createObj(IOpaqueAddress* pAddr, DataObject*& pObj) +{ + //StatusCode sc = StatusCode::SUCCESS; + MsgStream log(msgSvc(), "CaloNuIDDetDescrCnv"); + log << MSG::INFO << "in createObj: creating an CaloNuID helper object in the detector store" << endmsg; + + // Create a new CaloNuID + + DetDescrAddress* ddAddr; + ddAddr = dynamic_cast<DetDescrAddress*> (pAddr); + if(!ddAddr) { + log << MSG::FATAL << "Could not cast to DetDescrAddress." << endmsg; + return StatusCode::FAILURE; + } + + // Get the StoreGate key of this container. + std::string helperKey = *( ddAddr->par() ); + if ("" == helperKey) { + log << MSG::DEBUG << "No Helper key " << endmsg; + } + else { + log << MSG::DEBUG << "Helper key is " << helperKey << endmsg; + } + + + // get DetectorStore service + StoreGateSvc * detStore; + StatusCode status = serviceLocator()->service("DetectorStore", detStore); + if (status.isFailure()) { + log << MSG::FATAL << "DetectorStore service not found !" << endmsg; + return StatusCode::FAILURE; + } else {} + + // Get the dictionary manager from the detector store + const IdDictManager* idDictMgr; + status = detStore->retrieve(idDictMgr, "IdDict"); + if (status.isFailure()) { + log << MSG::FATAL << "Could not get IdDictManager !" << endmsg; + return StatusCode::FAILURE; + } + else { + log << MSG::DEBUG << " Found the IdDictManager. " << endmsg; + } + + // Only create new helper if it is the first pass or if there is a + // change in the the file or tag + bool initHelper = false; + + const IdDictMgr* mgr = idDictMgr->manager(); + + // Internal Calo id tag + std::string caloIDTag = mgr->tag(); + + // DoChecks flag + bool doChecks = mgr->do_checks(); + + IdDictDictionary* dict = mgr->find_dictionary("Calorimeter"); + if (!dict) { + log << MSG::ERROR + << "unable to find idDict for Calorimeter" + << endmsg; + return StatusCode::FAILURE; + } + + // File to be read for Calo ids + std::string caloIDFileName = dict->file_name(); + + // Tag of RDB record for Calo ids + std::string caloIdDictTag = dict->dict_tag(); + + + if (m_calonuId) { + + // CaloNu id helper already exists - second pass. Check for a + // change + if (caloIDTag != m_caloIDTag) { + // Internal Calo id tag + initHelper = true; + log << MSG::DEBUG << " Changed internal Calo id tag: " + << caloIDTag << endmsg; + } + if (caloIDFileName != m_caloIDFileName) { + // File to be read for Calo ids + initHelper = true; + log << MSG::DEBUG << " Changed CaloFileName:" + << caloIDFileName << endmsg; + } + if (caloIdDictTag != m_caloIdDictTag) { + // Tag of RDB record for Calo ids + initHelper = true; + log << MSG::DEBUG << " Changed CaloIdDictTag: " + << caloIdDictTag + << endmsg; + } + if (doChecks != m_doChecks) { + // DoChecks flag + initHelper = true; + log << MSG::DEBUG << " Changed doChecks flag: " + << doChecks + << endmsg; + } + } + else { + // create the helper + m_calonuId = new CaloNuID; + initHelper = true; + // add in message service for printout + m_calonuId->setMessageSvc(msgSvc()); + } + + if (initHelper) { + if (idDictMgr->initializeHelper(*m_calonuId)) { + log << MSG::ERROR << "Unable to initialize CaloNuID" << endmsg; + return StatusCode::FAILURE; + } + // Save state: + m_caloIDTag = caloIDTag; + m_caloIDFileName = caloIDFileName; + m_caloIdDictTag = caloIdDictTag; + m_doChecks = doChecks; + } + + // Pass a pointer to the container to the Persistency service by reference. + pObj = SG::asStorable(m_calonuId); + + return StatusCode::SUCCESS; + +} + +//-------------------------------------------------------------------- + +long +CaloNuIDDetDescrCnv::storageType() +{ + return DetDescr_StorageType; +} + +//-------------------------------------------------------------------- +const CLID& +CaloNuIDDetDescrCnv::classID() { + return ClassID_traits<CaloNuID>::ID(); +} + +//-------------------------------------------------------------------- +CaloNuIDDetDescrCnv::CaloNuIDDetDescrCnv(ISvcLocator* svcloc) + : + DetDescrConverter(ClassID_traits<CaloNuID>::ID(), svcloc), + m_calonuId(0), + m_doChecks(false) + +{} + diff --git a/Calorimeter/CaloDetDescrCnv/CaloIdCnv/src/CaloNuIDDetDescrCnv.h b/Calorimeter/CaloDetDescrCnv/CaloIdCnv/src/CaloNuIDDetDescrCnv.h new file mode 100644 index 0000000000000000000000000000000000000000..4e0c96c838e549954b5b62e6c1203c5675e8bdb4 --- /dev/null +++ b/Calorimeter/CaloDetDescrCnv/CaloIdCnv/src/CaloNuIDDetDescrCnv.h @@ -0,0 +1,71 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +/*************************************************************************** + Calo DetDescrCnv package + ----------------------------------------- + ***************************************************************************/ + +#ifndef CALOIDCNV_CALONUIDDETDESCRCNV_H +#define CALOIDCNV_CALONUIDDETDESCRCNV_H + +//<<<<<< INCLUDES >>>>>> + +#include "DetDescrCnvSvc/DetDescrConverter.h" + +//<<<<<< PUBLIC DEFINES >>>>>> +//<<<<<< PUBLIC CONSTANTS >>>>>> +//<<<<<< PUBLIC TYPES >>>>>> + +class CaloNuID; + +//<<<<<< PUBLIC VARIABLES >>>>>> +//<<<<<< PUBLIC FUNCTIONS >>>>>> +//<<<<<< CLASS DECLARATIONS >>>>>> + + +/** + ** This class is a converter for the CaloNuID an IdHelper which is + ** stored in the detector store. This class derives from + ** DetDescrConverter which is a converter of the DetDescrCnvSvc. + ** + **/ + +class CaloNuIDDetDescrCnv: public DetDescrConverter { + +public: + virtual long int repSvcType() const; + virtual StatusCode initialize(); + virtual StatusCode finalize(); + virtual StatusCode createObj(IOpaqueAddress* pAddr, DataObject*& pObj); + + // Storage type and class ID (used by CnvFactory) + static long storageType(); + static const CLID& classID(); + + CaloNuIDDetDescrCnv(ISvcLocator* svcloc); + +private: + /// The helper - only will create it once + CaloNuID* m_calonuId; + + /// File to be read for Scint ids + std::string m_caloIDFileName; + + /// Tag of RDB record for Scint ids + std::string m_caloIdDictTag; + + /// Internal Scint id tag + std::string m_caloIDTag; + + /// Whether or not + bool m_doChecks; + +}; + + +//<<<<<< INLINE PUBLIC FUNCTIONS >>>>>> +//<<<<<< INLINE MEMBER FUNCTIONS >>>>>> + +#endif // CALOIDCNV_CALONUIDDETDESCRCNV_H diff --git a/Calorimeter/CaloRecAlgs/python/CaloRecAlgsConfig.py b/Calorimeter/CaloRecAlgs/python/CaloRecAlgsConfig.py index 7204d63c7fbf6f79c6804c5c1026b7b421afc082..fde1341c389fe5ebf3093dd62a88605ef7ff30cf 100644 --- a/Calorimeter/CaloRecAlgs/python/CaloRecAlgsConfig.py +++ b/Calorimeter/CaloRecAlgs/python/CaloRecAlgsConfig.py @@ -19,10 +19,12 @@ def CalorimeterReconstructionCfg(flags, **kwargs): kwargs.setdefault("CaloWaveHitContainerKey", "CaloWaveformHits") kwargs.setdefault("Calo2WaveHitContainerKey", "Calo2WaveformHits") + kwargs.setdefault("CaloNuWaveHitContainerKey", "CaloNuWaveformHits") kwargs.setdefault("PreshowerWaveHitContainerKey", "PreshowerWaveformHits") kwargs.setdefault("CaloHitContainerKey", "CaloHits") kwargs.setdefault("Calo2HitContainerKey", "Calo2Hits") + kwargs.setdefault("CaloNuHitContainerKey", "CaloNuHits") kwargs.setdefault("PreshowerHitContainerKey", "PreshowerHits") acc.merge(CaloRecToolCfg(flags, **kwargs)) diff --git a/Calorimeter/CaloRecAlgs/src/CaloRecAlg.cxx b/Calorimeter/CaloRecAlgs/src/CaloRecAlg.cxx index 4e60ea011ed392b34fff441cf9807b352d14d04d..54015ecec729bf65d30e0dbdcc8730b13c9f6a1c 100644 --- a/Calorimeter/CaloRecAlgs/src/CaloRecAlg.cxx +++ b/Calorimeter/CaloRecAlgs/src/CaloRecAlg.cxx @@ -13,6 +13,7 @@ StatusCode CaloRecAlg::initialize() { // Set key to read calo hits from ATH_CHECK( m_caloWaveHitContainerKey.initialize() ); ATH_CHECK( m_calo2WaveHitContainerKey.initialize() ); + ATH_CHECK( m_caloNuWaveHitContainerKey.initialize() ); // Set key to read preshower hits from ATH_CHECK( m_preshowerWaveHitContainerKey.initialize() ); @@ -20,6 +21,7 @@ StatusCode CaloRecAlg::initialize() { // Set key to write container ATH_CHECK( m_caloHitContainerKey.initialize() ); ATH_CHECK( m_calo2HitContainerKey.initialize() ); + ATH_CHECK( m_caloNuHitContainerKey.initialize() ); ATH_CHECK( m_preshowerHitContainerKey.initialize() ); // Initalize tools @@ -51,6 +53,8 @@ StatusCode CaloRecAlg::execute(const EventContext& ctx) const { } SG::ReadHandle<xAOD::WaveformHitContainer> calo2WaveHitHandle(m_calo2WaveHitContainerKey, ctx); + + SG::ReadHandle<xAOD::WaveformHitContainer> caloNuWaveHitHandle(m_caloNuWaveHitContainerKey, ctx); SG::ReadHandle<xAOD::WaveformHitContainer> preshowerWaveHitHandle(m_preshowerWaveHitContainerKey, ctx); @@ -95,7 +99,7 @@ StatusCode CaloRecAlg::execute(const EventContext& ctx) const { } ATH_MSG_DEBUG("PreshowerHitContainer '" << preshowerHitContainerHandle.name() << "' filled with "<< preshowerHitContainerHandle->size() <<" items"); - // High-gain calo isn't guaranteed to exist + // High-range calo isn't guaranteed to exist if ( calo2WaveHitHandle.isValid() ) { ATH_MSG_DEBUG("Found ReadHandle for WaveformHitContainer " << m_calo2WaveHitContainerKey); @@ -103,7 +107,7 @@ StatusCode CaloRecAlg::execute(const EventContext& ctx) const { ATH_MSG_DEBUG("Calorimeter 2 Waveform Hit container found with zero length!"); } - // Reconstruct high-gain calorimeter hits + // Reconstruct high-range calorimeter hits SG::WriteHandle<xAOD::CalorimeterHitContainer> calo2HitContainerHandle(m_calo2HitContainerKey, ctx); ATH_CHECK( calo2HitContainerHandle.record( std::make_unique<xAOD::CalorimeterHitContainer>(), std::make_unique<xAOD::CalorimeterHitAuxContainer>() ) ); @@ -122,6 +126,33 @@ StatusCode CaloRecAlg::execute(const EventContext& ctx) const { ATH_MSG_DEBUG("No ReadHandle for WaveformHitContainer " << m_calo2WaveHitContainerKey); } + // CaloNu isn't guaranteed to exist + if ( caloNuWaveHitHandle.isValid() ) { + ATH_MSG_DEBUG("Found ReadHandle for WaveformHitContainer " << m_caloNuWaveHitContainerKey); + + if (caloNuWaveHitHandle->size() == 0) { + ATH_MSG_DEBUG("Calorimeter 2 Waveform Hit container found with zero length!"); + } + + // Reconstruct CaloNu calorimeter hits + SG::WriteHandle<xAOD::CalorimeterHitContainer> caloNuHitContainerHandle(m_caloNuHitContainerKey, ctx); + ATH_CHECK( caloNuHitContainerHandle.record( std::make_unique<xAOD::CalorimeterHitContainer>(), + std::make_unique<xAOD::CalorimeterHitAuxContainer>() ) ); + ATH_MSG_DEBUG("WaveformsHitContainer '" << caloNuHitContainerHandle.name() << "' initialized"); + + for( const auto& hit : *caloNuWaveHitHandle ) { + if (hit->status_bit(xAOD::WaveformStatus::SECONDARY)) continue; + xAOD::CalorimeterHit* calo_hit = new xAOD::CalorimeterHit(); + caloNuHitContainerHandle->push_back(calo_hit); + calo_hit->addHit(caloNuWaveHitHandle.get(), hit); + m_recoCalibTool->reconstruct(ctx, calo_hit, correct_gain=false); + } + ATH_MSG_DEBUG("CaloNuHitContainer '" << caloNuHitContainerHandle.name() << "' filled with "<< caloNuHitContainerHandle->size() <<" items"); + + } else { + ATH_MSG_DEBUG("No ReadHandle for WaveformHitContainer " << m_caloNuWaveHitContainerKey); + } + return StatusCode::SUCCESS; } diff --git a/Calorimeter/CaloRecAlgs/src/CaloRecAlg.h b/Calorimeter/CaloRecAlgs/src/CaloRecAlg.h index b11fc05ae5cf91b8e5b4aed67074d07674a511a7..f5953ecfa25df972611ccb2e30bce5ca9b10f567 100644 --- a/Calorimeter/CaloRecAlgs/src/CaloRecAlg.h +++ b/Calorimeter/CaloRecAlgs/src/CaloRecAlg.h @@ -75,6 +75,10 @@ class CaloRecAlg : public AthReentrantAlgorithm { SG::ReadHandleKey<xAOD::WaveformHitContainer> m_calo2WaveHitContainerKey {this, "Calo2WaveHitContainerKey", "Calo2WaveformHits"}; //@} + //@{ + SG::ReadHandleKey<xAOD::WaveformHitContainer> m_caloNuWaveHitContainerKey {this, "CaloNuWaveHitContainerKey", "CaloNuWaveformHits"}; + //@} + //@{ SG::ReadHandleKey<xAOD::WaveformHitContainer> m_preshowerWaveHitContainerKey {this, "PreshowerWaveHitContainerKey", "PreshowerWaveformHits"}; //@} @@ -85,6 +89,7 @@ class CaloRecAlg : public AthReentrantAlgorithm { //@{ SG::WriteHandleKey<xAOD::CalorimeterHitContainer> m_caloHitContainerKey {this, "CaloHitContainerKey", "CaloHits"}; SG::WriteHandleKey<xAOD::CalorimeterHitContainer> m_calo2HitContainerKey {this, "Calo2HitContainerKey", "Calo2Hits"}; + SG::WriteHandleKey<xAOD::CalorimeterHitContainer> m_caloNuHitContainerKey {this, "CaloNuHitContainerKey", "CaloNuHits"}; SG::WriteHandleKey<xAOD::CalorimeterHitContainer> m_preshowerHitContainerKey {this, "PreshowerHitContainerKey", "PreshowerHits"}; //@} diff --git a/Calorimeter/CaloRecTools/src/CaloRecTool.cxx b/Calorimeter/CaloRecTools/src/CaloRecTool.cxx index 01a81e287ca312ecde8616cf22a1c23a29186767..c09c2760136a4b539a3013d380d8116e10001298 100644 --- a/Calorimeter/CaloRecTools/src/CaloRecTool.cxx +++ b/Calorimeter/CaloRecTools/src/CaloRecTool.cxx @@ -41,19 +41,40 @@ CaloRecTool::initialize() { HVgaincurves_rootFile->Close(); // close the root file // These should be in DB, but just hardcode this for now + // This is a bit ugly, as channel mappings hav changed with the years + // but for now we can still cover all options + + // Paramters to convert N_mip to E_dep + + // Original ECal or CaloLo m_MIP_sim_Edep[0] = m_MIP_sim_Edep_calo.value(); m_MIP_sim_Edep[1] = m_MIP_sim_Edep_calo.value(); m_MIP_sim_Edep[2] = m_MIP_sim_Edep_calo.value(); m_MIP_sim_Edep[3] = m_MIP_sim_Edep_calo.value(); - m_MIP_sim_Edep[12] = m_MIP_sim_Edep_preshower.value(); - m_MIP_sim_Edep[13] = m_MIP_sim_Edep_preshower.value(); - + // CaloHi m_MIP_sim_Edep[16] = m_MIP_sim_Edep_calo2.value(); m_MIP_sim_Edep[17] = m_MIP_sim_Edep_calo2.value(); m_MIP_sim_Edep[18] = m_MIP_sim_Edep_calo2.value(); m_MIP_sim_Edep[19] = m_MIP_sim_Edep_calo2.value(); + // CaloNu (2 locations) + m_MIP_sim_Edep[20] = m_MIP_sim_Edep_calonu.value(); + m_MIP_sim_Edep[21] = m_MIP_sim_Edep_calonu.value(); + m_MIP_sim_Edep[22] = m_MIP_sim_Edep_calonu.value(); + m_MIP_sim_Edep[23] = m_MIP_sim_Edep_calonu.value(); + + m_MIP_sim_Edep[6] = m_MIP_sim_Edep_calonu.value(); + m_MIP_sim_Edep[7] = m_MIP_sim_Edep_calonu.value(); + m_MIP_sim_Edep[14] = m_MIP_sim_Edep_calonu.value(); + m_MIP_sim_Edep[15] = m_MIP_sim_Edep_calonu.value(); + + // Preshower (always in same place) + m_MIP_sim_Edep[12] = m_MIP_sim_Edep_preshower.value(); + m_MIP_sim_Edep[13] = m_MIP_sim_Edep_preshower.value(); + + // Paramters to convert N_mip to E_EM + // Conversion to EM energy scale (same for all calorimeters) m_EM_mu_Map[0] = m_calo_EM_mu.value(); m_EM_mu_Map[1] = m_calo_EM_mu.value(); m_EM_mu_Map[2] = m_calo_EM_mu.value(); @@ -64,6 +85,20 @@ CaloRecTool::initialize() { m_EM_mu_Map[18] = m_calo_EM_mu.value(); m_EM_mu_Map[19] = m_calo_EM_mu.value(); + m_EM_mu_Map[20] = m_calo_EM_mu.value(); + m_EM_mu_Map[21] = m_calo_EM_mu.value(); + m_EM_mu_Map[22] = m_calo_EM_mu.value(); + m_EM_mu_Map[23] = m_calo_EM_mu.value(); + + m_EM_mu_Map[6] = m_calo_EM_mu.value(); + m_EM_mu_Map[7] = m_calo_EM_mu.value(); + m_EM_mu_Map[14] = m_calo_EM_mu.value(); + m_EM_mu_Map[15] = m_calo_EM_mu.value(); + + // Missing this for preshower? + m_EM_mu_Map[12] = m_preshower_EM_mu.value(); + m_EM_mu_Map[13] = m_preshower_EM_mu.value(); + return StatusCode::SUCCESS; } @@ -235,6 +270,9 @@ CaloRecTool::reconstruct(const EventContext& ctx, // Get the waveform hit attached to this calo hit const xAOD::WaveformHit* wave_hit = calo_hit->Hit(0); ATH_MSG_DEBUG("calo_hit in channel " << wave_hit->channel() ); + + // Must set channel + calo_hit->set_channel(wave_hit->channel()); float MIPcharge_ref = getMIPcharge_ref(ctx, wave_hit->channel()); // get reference MIP charge from database diff --git a/Calorimeter/CaloRecTools/src/CaloRecTool.h b/Calorimeter/CaloRecTools/src/CaloRecTool.h index 82ba2b60740dade0e64e91273e089d2ced98780a..46c24bd73ed290101a6d02a8f85de9393faf4087 100644 --- a/Calorimeter/CaloRecTools/src/CaloRecTool.h +++ b/Calorimeter/CaloRecTools/src/CaloRecTool.h @@ -90,12 +90,16 @@ class CaloRecTool: public extends<AthAlgTool, ICaloRecTool> { SG::ReadCondHandleKey<CondAttrListCollection> m_MIP_ref_ReadKey{this, "MIP_ref_ReadKey", "/WAVE/Calibration/MIP_ref", "Key of folder for MIP charge calibration measurment, also stores PMT HV used to measure the reference MIP charge"}; // Could also put these in DB, but just hardcode them for now - FloatProperty m_MIP_sim_Edep_calo {this, "MIP_sim_Edep_calo", 58.5}; // MIP deposits 5.85 MeV of energy in calo - FloatProperty m_MIP_sim_Edep_calo2 {this, "MIP_sim_Edep_calo2", 58.5}; // MIP deposits 5.85 MeV of energy in calo + FloatProperty m_MIP_sim_Edep_calo {this, "MIP_sim_Edep_calo", 58.5}; // MIP deposits 58.5 MeV of energy in calo + FloatProperty m_MIP_sim_Edep_calo2 {this, "MIP_sim_Edep_calo2", 58.5}; // MIP deposits 58.5 MeV of energy in calo + FloatProperty m_MIP_sim_Edep_calonu {this, "MIP_sim_Edep_calonu", 58.5}; // MIP deposits 58.5 MeV of energy in calo FloatProperty m_MIP_sim_Edep_preshower {this, "MIP_sim_Edep_preshower", 4.894}; // MIP deposits 4.894 MeV of energy in a preshower layer FloatProperty m_calo_EM_mu {this, "m_calo_EM_mu", 330.0}; // factor used to do rough calibration of calo to EM energy: 0.33 GeV or 330 MeV + // This isn't calibrated yet, just use CALO value for the moment + FloatProperty m_preshower_EM_mu {this, "m_preshower_EM_mu", 330.0}; // factor used to do rough calibration of calo to EM energy: 0.33 GeV or 330 MeV + float m_MIP_sim_Edep[32]; // vector that holds Edep factors for calo and preshower float m_EM_mu_Map[32]; // vector that holds EM_mu calibration factors for calo channels diff --git a/Control/CalypsoExample/Reconstruction/scripts/faser_reco.py b/Control/CalypsoExample/Reconstruction/scripts/faser_reco.py index 8923c532622198918c71536fe191008f5a0b38c1..c43e75440dbfcb2a3fd0c64724db2e12149d9a86 100755 --- a/Control/CalypsoExample/Reconstruction/scripts/faser_reco.py +++ b/Control/CalypsoExample/Reconstruction/scripts/faser_reco.py @@ -167,7 +167,7 @@ elif runtype in ["TI12Data03", "TI12MC03"]: # Updated 2023 TI12 geometry elif runtype in ["TI12Data04", "TI12MC04"]: configFlags.GeoModel.FaserVersion = "FASERNU-04" - configFlags.IOVDb.GlobalTag = "OFLCOND-FASER-04" + configFlags.IOVDb.GlobalTag = "OFLCOND-FASER-05" # Latest 2025 alignment useCal = True if not args.isMC: useLHC = True diff --git a/Control/CalypsoExample/WaveformDataAccessExample/src/RawWaveformAccess.cxx b/Control/CalypsoExample/WaveformDataAccessExample/src/RawWaveformAccess.cxx index 166d219c6fe29670843d5169ba5fea1c597c45f3..52cdd42b41e9d5746e5913c3f6fab9b169aedd31 100644 --- a/Control/CalypsoExample/WaveformDataAccessExample/src/RawWaveformAccess.cxx +++ b/Control/CalypsoExample/WaveformDataAccessExample/src/RawWaveformAccess.cxx @@ -28,9 +28,11 @@ RawWaveformAccess::initialize() // Must initialize SG handles ATH_CHECK( m_CaloWaveformContainer.initialize() ); ATH_CHECK( m_Calo2WaveformContainer.initialize() ); + ATH_CHECK( m_CaloNuWaveformContainer.initialize() ); ATH_CHECK( m_VetoWaveformContainer.initialize() ); ATH_CHECK( m_TriggerWaveformContainer.initialize() ); ATH_CHECK( m_PreshowerWaveformContainer.initialize() ); + ATH_CHECK( m_MuonWaveformContainer.initialize() ); ATH_CHECK( m_ClockWaveformContainer.initialize() ); return StatusCode::SUCCESS; @@ -56,7 +58,11 @@ RawWaveformAccess::execute(const EventContext& ctx) const SG::ReadHandle<RawWaveformContainer> calo2Handle(m_Calo2WaveformContainer, ctx); ATH_MSG_INFO("Found ReadHandle for Calo2Waveforms"); - ATH_MSG_INFO(*caloHandle); + ATH_MSG_INFO(*calo2Handle); + + SG::ReadHandle<RawWaveformContainer> caloNuHandle(m_CaloNuWaveformContainer, ctx); + ATH_MSG_INFO("Found ReadHandle for CaloNuWaveforms"); + ATH_MSG_INFO(*caloNuHandle); SG::ReadHandle<RawWaveformContainer> vetoHandle(m_VetoWaveformContainer, ctx); ATH_MSG_INFO("Found ReadHandle for VetoWaveforms"); @@ -70,6 +76,10 @@ RawWaveformAccess::execute(const EventContext& ctx) const ATH_MSG_INFO("Found ReadHandle for PreshowerWaveforms"); ATH_MSG_INFO(*preshowerHandle); + SG::ReadHandle<RawWaveformContainer> muonHandle(m_MuonWaveformContainer, ctx); + ATH_MSG_INFO("Found ReadHandle for MuonWaveforms"); + ATH_MSG_INFO(*muonHandle); + SG::ReadHandle<RawWaveformContainer> clockHandle(m_ClockWaveformContainer, ctx); ATH_MSG_INFO("Found ReadHandle for ClockWaveforms"); ATH_MSG_INFO(*clockHandle); diff --git a/Control/CalypsoExample/WaveformDataAccessExample/src/RawWaveformAccess.h b/Control/CalypsoExample/WaveformDataAccessExample/src/RawWaveformAccess.h index b07edde805c383b9b3750a10953df27b8aa28df7..f73314ffd84c0fd1d3bf889c30163382aaa80590 100644 --- a/Control/CalypsoExample/WaveformDataAccessExample/src/RawWaveformAccess.h +++ b/Control/CalypsoExample/WaveformDataAccessExample/src/RawWaveformAccess.h @@ -34,12 +34,16 @@ class RawWaveformAccess: public AthReentrantAlgorithm { this, "CaloWaveformContainerKey", "CaloWaveforms", "ReadHandleKey for CaloWaveforms Container"}; SG::ReadHandleKey<RawWaveformContainer> m_Calo2WaveformContainer { this, "Calo2WaveformContainerKey", "Calo2Waveforms", "ReadHandleKey for Calo2Waveforms Container"}; + SG::ReadHandleKey<RawWaveformContainer> m_CaloNuWaveformContainer + { this, "CaloNuWaveformContainerKey", "CaloNuWaveforms", "ReadHandleKey for CaloNuWaveforms Container"}; SG::ReadHandleKey<RawWaveformContainer> m_VetoWaveformContainer - { this, "VetoWaveformContainerKey", "VetoWaveforms", "ReadHandleKey for CaloWaveforms Container"}; + { this, "VetoWaveformContainerKey", "VetoWaveforms", "ReadHandleKey for VetoWaveforms Container"}; SG::ReadHandleKey<RawWaveformContainer> m_TriggerWaveformContainer { this, "TriggerWaveformContainerKey", "TriggerWaveforms", "ReadHandleKey for TriggerWaveforms Container"}; SG::ReadHandleKey<RawWaveformContainer> m_PreshowerWaveformContainer { this, "PreshowerWaveformContainerKey", "PreshowerWaveforms", "ReadHandleKey for PreshowerWaveforms Container"}; + SG::ReadHandleKey<RawWaveformContainer> m_MuonWaveformContainer + { this, "MuonWaveformContainerKey", "MuonWaveforms", "ReadHandleKey for MuonWaveforms Container"}; SG::ReadHandleKey<RawWaveformContainer> m_ClockWaveformContainer { this, "ClockWaveformContainerKey", "ClockWaveforms", "ReadHandleKey for ClockWaveforms Container"}; }; diff --git a/DetectorDescription/DetDescrCnvSvc/src/DetDescrCnvSvc.cxx b/DetectorDescription/DetDescrCnvSvc/src/DetDescrCnvSvc.cxx index cc2fca779acd953d177963424389477baa30c856..0fd7d530d9f45faeca8a8b0ec9c371d41dc2a28c 100644 --- a/DetectorDescription/DetDescrCnvSvc/src/DetDescrCnvSvc.cxx +++ b/DetectorDescription/DetDescrCnvSvc/src/DetDescrCnvSvc.cxx @@ -127,10 +127,14 @@ DetDescrCnvSvc::initialize() { if (status != StatusCode::SUCCESS) return status; status = addToDetStore(247779284, "VetoNuID"); if (status != StatusCode::SUCCESS) return status; + status = addToDetStore(143274416, "MuonID"); + if (status != StatusCode::SUCCESS) return status; status = addToDetStore(205618430, "FaserSCT_ID"); if (status != StatusCode::SUCCESS) return status; status = addToDetStore(113753346, "EcalID"); if (status != StatusCode::SUCCESS) return status; + status = addToDetStore(167327975, "CaloNuID"); + if (status != StatusCode::SUCCESS) return status; return status; } diff --git a/DetectorDescription/FaserDetDescr/FaserDetDescr/FaserDetTechnology.h b/DetectorDescription/FaserDetDescr/FaserDetDescr/FaserDetTechnology.h index 0ee1ecc5d64e53a1d5cd0e04ad969421f8344c59..0bb74ba7b5c9a1e76267b71991315698ca8060ef 100644 --- a/DetectorDescription/FaserDetDescr/FaserDetDescr/FaserDetTechnology.h +++ b/DetectorDescription/FaserDetDescr/FaserDetDescr/FaserDetTechnology.h @@ -39,17 +39,19 @@ namespace FaserDetDescr { fFaserVeto = 3, fFaserTrigger = 4, fFaserPreshower = 5, - fLastFaserScintillatorTechnology = 5, + fFaserMuon = 6, + fLastFaserScintillatorTechnology = 6, // Tracker - fFirstFaserTrackerTechnology = 6, - fFaserSCT = 6, - fLastFaserTrackerTechnology = 6, + fFirstFaserTrackerTechnology = 7, + fFaserSCT = 7, + fLastFaserTrackerTechnology = 7, // Calorimeter - fFirstFaserCalorimeterTechnology = 7, - fFaserECAL = 7, - fLastFaserCalorimeterTechnology = 7, + fFirstFaserCalorimeterTechnology = 8, + fFaserECAL = 8, + fFaserCaloNu = 9, + fLastFaserCalorimeterTechnology = 9, // number of defined detector technologies - fNumFaserDetTechnologies = 8 + fNumFaserDetTechnologies = 10 }; } // end of namespace diff --git a/DetectorDescription/FaserDetDescr/FaserDetDescr/FaserDetectorID.h b/DetectorDescription/FaserDetDescr/FaserDetDescr/FaserDetectorID.h index 3ac1160a9e0c12935f522b0750b09a74fe4d4983..e745518739f8f78f74ff76ea8a32f9bf1df1e068 100644 --- a/DetectorDescription/FaserDetDescr/FaserDetDescr/FaserDetectorID.h +++ b/DetectorDescription/FaserDetDescr/FaserDetDescr/FaserDetectorID.h @@ -85,6 +85,7 @@ public: Identifier vetonu (void) const; Identifier trigger (void) const; Identifier preshower (void) const; + Identifier muon (void) const; //@} /// @name Tracker subsystem ids @@ -95,6 +96,7 @@ public: /// @name Calorimeter subsystem ids //@{ Identifier ecal (void) const; + Identifier calonu (void) const; //@} /// @name Contexts to provide id length - e.g. for use in generic decoding @@ -161,8 +163,10 @@ public: bool is_vetonu (Identifier id) const; bool is_trigger (Identifier id) const; bool is_preshower (Identifier id) const; + bool is_muon (Identifier id) const; bool is_sct (Identifier id) const; bool is_ecal (Identifier id) const; + bool is_calonu (Identifier id) const; //@} @@ -177,8 +181,10 @@ public: bool is_vetonu (const ExpandedIdentifier& id) const; bool is_trigger (const ExpandedIdentifier& id) const; bool is_preshower (const ExpandedIdentifier& id) const; + bool is_muon (const ExpandedIdentifier& id) const; bool is_sct (const ExpandedIdentifier& id) const; bool is_ecal (const ExpandedIdentifier& id) const; + bool is_calonu (const ExpandedIdentifier& id) const; //@} /// @name Dictionary versioning: provide access to dictionary names and versions. Note that a helper may correspond to one or more id dictionary @@ -236,12 +242,14 @@ protected: ExpandedIdentifier vetonu_exp (void) const; ExpandedIdentifier trigger_exp (void) const; ExpandedIdentifier preshower_exp (void) const; + ExpandedIdentifier muon_exp (void) const; /// Tracker: ExpandedIdentifier sct_exp (void) const; /// Calorimeter: ExpandedIdentifier ecal_exp (void) const; + ExpandedIdentifier calonu_exp (void) const; /// Provide efficient access to individual field values, for /// subclass idhelpers @@ -254,8 +262,10 @@ protected: int vetonu_field_value () const; int trigger_field_value () const; int preshower_field_value () const; + int muon_field_value () const; int sct_field_value () const; int ecal_field_value () const; + int calonu_field_value () const; /// Register the file and tag names for a particular IdDict /// dictionary @@ -311,12 +321,14 @@ private: int m_CALO_ID; int m_EMULSION_ID; int m_VETO_ID; - int m_VETONU_ID; int m_TRIGGER_ID; int m_PRESHOWER_ID; + int m_VETONU_ID; + int m_MUON_ID; int m_SCT_ID; int m_ECAL_ID; - + int m_CALONU_ID; + /// Flag for slhc layout: bool m_isSLHC; @@ -409,6 +421,12 @@ FaserDetectorID::preshower_exp (void) const return (result << m_PRESHOWER_ID); } +inline ExpandedIdentifier +FaserDetectorID::muon_exp (void) const +{ + ExpandedIdentifier result(scint_exp()); + return (result << m_MUON_ID); +} inline ExpandedIdentifier FaserDetectorID::sct_exp (void) const { @@ -423,8 +441,15 @@ FaserDetectorID::ecal_exp (void) const return (result << m_ECAL_ID); } +inline ExpandedIdentifier +FaserDetectorID::calonu_exp (void) const +{ + ExpandedIdentifier result(calo_exp()); + return (result << m_CALONU_ID); +} + inline int -FaserDetectorID::neutrino_field_value () const {return (m_NEUTRINO_ID);} +FaserDetectorID::neutrino_field_value () const {return (m_NEUTRINO_ID);} inline int FaserDetectorID::scint_field_value () const {return (m_SCINT_ID);} @@ -436,7 +461,7 @@ inline int FaserDetectorID::calo_field_value () const {return (m_CALO_ID);} inline int -FaserDetectorID::emulsion_field_value () const {return (m_EMULSION_ID);} +FaserDetectorID::emulsion_field_value () const {return (m_EMULSION_ID);} inline int FaserDetectorID::veto_field_value () const {return (m_VETO_ID);} @@ -445,10 +470,13 @@ inline int FaserDetectorID::vetonu_field_value () const {return (m_VETONU_ID);} inline int -FaserDetectorID::trigger_field_value () const {return (m_TRIGGER_ID);} +FaserDetectorID::trigger_field_value () const {return (m_TRIGGER_ID);} inline int -FaserDetectorID::preshower_field_value () const {return (m_PRESHOWER_ID);} +FaserDetectorID::preshower_field_value () const {return (m_PRESHOWER_ID);} + +inline int +FaserDetectorID::muon_field_value () const {return (m_MUON_ID);} inline int FaserDetectorID::sct_field_value () const {return (m_SCT_ID);} @@ -456,6 +484,9 @@ FaserDetectorID::sct_field_value () const {return (m_SCT_ID);} inline int FaserDetectorID::ecal_field_value () const {return (m_ECAL_ID);} +inline int +FaserDetectorID::calonu_field_value () const {return (m_CALONU_ID);} + inline bool FaserDetectorID::is_neutrino (Identifier id) const { @@ -530,6 +561,16 @@ FaserDetectorID::is_preshower (Identifier id) const return result; } +inline bool +FaserDetectorID::is_muon (Identifier id) const +{ + bool result = false; + if(is_scint(id)) { + result = (m_scint_part_impl.unpack(id) == m_MUON_ID); + } + return result; +} + inline bool FaserDetectorID::is_sct (Identifier id) const { @@ -550,4 +591,14 @@ FaserDetectorID::is_ecal (Identifier id) const return result; } +inline bool +FaserDetectorID::is_calonu (Identifier id) const +{ + bool result = false; + if(is_calo(id)) { + result = (m_calo_part_impl.unpack(id) == m_CALONU_ID); + } + return result; +} + #endif // FASERDETDESCR_FASERDETECTORID_H diff --git a/DetectorDescription/FaserDetDescr/src/FaserDetectorID.cxx b/DetectorDescription/FaserDetDescr/src/FaserDetectorID.cxx index 59d81a8d8006bdde022b1db76092a6f97567e85e..308e1fa20f343a60909856afcff4efb527e82fce 100644 --- a/DetectorDescription/FaserDetDescr/src/FaserDetectorID.cxx +++ b/DetectorDescription/FaserDetDescr/src/FaserDetectorID.cxx @@ -36,17 +36,25 @@ FaserDetectorID::FaserDetectorID() m_is_initialized_from_dict(false), m_DET_INDEX(999), m_SUBDET_INDEX(999), + m_NEUTRINO_ID(1), m_SCINT_ID(2), m_TRACKER_ID(3), m_CALO_ID(4), + m_EMULSION_ID(1), + m_VETO_ID(1), - m_VETONU_ID(4), m_TRIGGER_ID(2), m_PRESHOWER_ID(3), + m_VETONU_ID(4), + m_MUON_ID(5), + m_SCT_ID(1), + m_ECAL_ID(1), + m_CALONU_ID(2), + m_isSLHC(false), m_faser_dict(0), m_neutrino_dict(0), @@ -81,8 +89,10 @@ FaserDetectorID::FaserDetectorID(const FaserDetectorID& other) m_VETONU_ID (other.m_VETONU_ID), m_TRIGGER_ID (other.m_TRIGGER_ID), m_PRESHOWER_ID (other.m_PRESHOWER_ID), + m_MUON_ID (other.m_MUON_ID), m_SCT_ID (other.m_SCT_ID), m_ECAL_ID (other.m_ECAL_ID), + m_CALONU_ID (other.m_CALONU_ID), m_isSLHC (other.m_isSLHC), m_faser_dict (other.m_faser_dict), m_neutrino_dict (other.m_neutrino_dict), @@ -125,8 +135,10 @@ FaserDetectorID::operator= (const FaserDetectorID& other) m_TRIGGER_ID = other.m_TRIGGER_ID; m_PRESHOWER_ID = other.m_PRESHOWER_ID; m_VETONU_ID = other.m_VETONU_ID; + m_MUON_ID = other.m_MUON_ID; m_SCT_ID = other.m_SCT_ID; m_ECAL_ID = other.m_ECAL_ID; + m_CALONU_ID = other.m_CALONU_ID; m_faser_dict = other.m_faser_dict; m_neutrino_dict = other.m_neutrino_dict; m_scint_dict = other.m_scint_dict; @@ -237,6 +249,16 @@ FaserDetectorID::preshower (void) const return (result); } +Identifier +FaserDetectorID::muon (void) const +{ + Identifier result((Identifier::value_type)0); + // Pack field + m_det_impl.pack (scint_field_value(), result); + m_scint_part_impl.pack(m_MUON_ID, result); + return (result); +} + Identifier FaserDetectorID::sct (void) const { @@ -257,6 +279,16 @@ FaserDetectorID::ecal (void) const return (result); } +Identifier +FaserDetectorID::calonu (void) const +{ + Identifier result((Identifier::value_type)0); + // Pack field + m_det_impl.pack (calo_field_value(), result); + m_calo_part_impl.pack(m_CALONU_ID, result); + return (result); +} + /// IdContext (indicates id length) for detector systems IdContext FaserDetectorID::detsystem_context (void) const @@ -487,6 +519,16 @@ FaserDetectorID::is_preshower (const ExpandedIdentifier& id) const return result; } +bool +FaserDetectorID::is_muon (const ExpandedIdentifier& id) const +{ + bool result = false; + if ( is_scint(id) && id.fields() > 1 ){ + if ( id[1] == m_MUON_ID ) result = true; + } + return result; +} + bool FaserDetectorID::is_sct (const ExpandedIdentifier& id) const { @@ -507,6 +549,16 @@ FaserDetectorID::is_ecal (const ExpandedIdentifier& id) const return result; } +bool +FaserDetectorID::is_calonu (const ExpandedIdentifier& id) const +{ + bool result = false; + if ( is_calo(id) && id.fields() > 1 ){ + if ( id[1] == m_CALONU_ID ) result = true; + } + return result; +} + // Short print out of any identifier: void FaserDetectorID::show (Identifier id, @@ -753,9 +805,11 @@ FaserDetectorID::initLevelsFromDict(const IdDictMgr& dict_mgr) m_TRIGGER_ID = -1; m_PRESHOWER_ID = -1; m_VETONU_ID = -1; + m_MUON_ID = -1; m_SCT_ID = -1; m_ECAL_ID = -1; - + m_CALONU_ID = -1; + // Save generic dict for top levels IdDictDictionary* top_dict = 0; @@ -990,6 +1044,36 @@ FaserDetectorID::initLevelsFromDict(const IdDictMgr& dict_mgr) return (1); } + label = field->find_label("Muon"); + if (label) { + if (label->m_valued) { + m_MUON_ID = label->m_value; + } + else { + if(m_msgSvc) { + MsgStream log(m_msgSvc, "FaserDetectorID" ); + log << MSG::ERROR << "initLevelsFromDict - label Muon does NOT have a value " + << endmsg; + } + else { + std::cout << "FaserDetectorID::initLevelsFromDict - label Muon does NOT have a value " + << std::endl; + } + return (1); + } + } + else { + if(m_msgSvc) { + MsgStream log(m_msgSvc, "FaserDetectorID" ); + log << MSG::ERROR << "initLevelsFromDict - unable to find 'Muon label " + << endmsg; + } + else { + std::cout << "FaserDetectorID::initLevelsFromDict - unable to find 'Muon' label " + << std::endl; + } + return (1); + } } @@ -1118,6 +1202,37 @@ FaserDetectorID::initLevelsFromDict(const IdDictMgr& dict_mgr) } return (1); } + + label = field->find_label("CaloNu"); + if (label) { + if (label->m_valued) { + m_CALONU_ID = label->m_value; + } + else { + if(m_msgSvc) { + MsgStream log(m_msgSvc, "FaserDetectorID" ); + log << MSG::ERROR << "initLevelsFromDict - label CALONU does NOT have a value " + << endmsg; + } + else { + std::cout << "FaserDetectorID::initLevelsFromDict - label CALONU does NOT have a value " + << std::endl; + } + return (1); + } + } + else { + if(m_msgSvc) { + MsgStream log(m_msgSvc, "FaserDetectorID" ); + log << MSG::ERROR << "initLevelsFromDict - unable to find 'CALONU' label " + << endmsg; + } + else { + std::cout << "FaserDetectorID::initLevelsFromDict - unable to find 'CALONU' label " + << std::endl; + } + return (1); + } } // set det/subdet indices diff --git a/DetectorDescription/FaserDetDescr/src/FaserDetectorIDHelper.cxx b/DetectorDescription/FaserDetDescr/src/FaserDetectorIDHelper.cxx index f192dcaff52bf68da5d9de6e815810b643963715..343be1f50fc9e8b8cff6601a8e9fd0a6a9db109a 100644 --- a/DetectorDescription/FaserDetDescr/src/FaserDetectorIDHelper.cxx +++ b/DetectorDescription/FaserDetDescr/src/FaserDetectorIDHelper.cxx @@ -30,12 +30,15 @@ FaserDetectorIDHelper::FaserDetectorIDHelper(void) m_isSLHC(false), m_emulsion_region_index(UNDEFINED), m_veto_region_index(UNDEFINED), + m_vetonu_region_index(UNDEFINED), m_trigger_region_index(UNDEFINED), m_preshower_region_index(UNDEFINED), - m_sct_region_index(UNDEFINED), - m_ecal_region_index(UNDEFINED), + m_muon_region_index(UNDEFINED), + m_sct_region_index(UNDEFINED), + m_ecal_region_index(UNDEFINED), + m_calonu_region_index(UNDEFINED), m_initialized(false), - m_msgSvc(0) + m_msgSvc(0) {} FaserDetectorIDHelper::~FaserDetectorIDHelper(void) @@ -99,7 +102,7 @@ FaserDetectorIDHelper::initialize_from_dictionary(const IdDictMgr& dict_mgr) } else { // Check if this is SLHC layout - m_isSLHC = (dict->m_version=="SLHC"); + //m_isSLHC = (dict->m_version=="SLHC"); // Save index to a VETO region for unpacking id = faser_id.veto_exp(); @@ -117,40 +120,70 @@ FaserDetectorIDHelper::initialize_from_dictionary(const IdDictMgr& dict_mgr) } } - //if (!m_isSLHC) { - - // Save index to a TRIGGER region for unpacking - id = faser_id.trigger_exp(); - if (dict->find_region(id, m_trigger_region_index)) { - if(m_msgSvc) { - MsgStream log(m_msgSvc, "FaserDetectorIDHelper" ); - log << MSG::WARNING << "initialize_from_dictionary - unable to find trigger region index: id, reg " - << (std::string)id << " " << m_trigger_region_index - << endmsg; - } - else { - std::cout << "FaserDetectorIDHelper::initialize_from_dictionary - Warning: unable to trigger sct region index: id, reg " - << (std::string)id << " " << m_trigger_region_index - << std::endl; - } - } + // Save index to a VETONU region for unpacking + id = faser_id.vetonu_exp(); + if (dict->find_region(id, m_vetonu_region_index)) { + if(m_msgSvc) { + MsgStream log(m_msgSvc, "FaserDetectorIDHelper" ); + log << MSG::WARNING << "initialize_from_dictionary - unable to find vetonu region index: id, reg " + << (std::string)id << " " << m_vetonu_region_index + << endmsg; + } + else { + std::cout << "FaserDetectorIDHelper::initialize_from_dictionary - Warning: unable to find vetonu region index: id, reg " + << (std::string)id << " " << m_vetonu_region_index + << std::endl; + } + } + + // Save index to a TRIGGER region for unpacking + id = faser_id.trigger_exp(); + if (dict->find_region(id, m_trigger_region_index)) { + if(m_msgSvc) { + MsgStream log(m_msgSvc, "FaserDetectorIDHelper" ); + log << MSG::WARNING << "initialize_from_dictionary - unable to find trigger region index: id, reg " + << (std::string)id << " " << m_trigger_region_index + << endmsg; + } + else { + std::cout << "FaserDetectorIDHelper::initialize_from_dictionary - Warning: unable to trigger sct region index: id, reg " + << (std::string)id << " " << m_trigger_region_index + << std::endl; + } + } - // Save index to a PRESHOWER region for unpacking - id = faser_id.preshower_exp(); - if (dict->find_region(id, m_preshower_region_index)) { - if(m_msgSvc) { - MsgStream log(m_msgSvc, "FaserDetectorIDHelper" ); - log << MSG::WARNING << "initialize_from_dictionary - unable to find preshower region index: id, reg " - << (std::string)id << " " << m_preshower_region_index - << endmsg; - } - else { - std::cout << "FaserDetectorIDHelper::initialize_from_dictionary - Warning: unable to find preshower region index: id, reg " - << (std::string)id << " " << m_preshower_region_index - << std::endl; - } + // Save index to a PRESHOWER region for unpacking + id = faser_id.preshower_exp(); + if (dict->find_region(id, m_preshower_region_index)) { + if(m_msgSvc) { + MsgStream log(m_msgSvc, "FaserDetectorIDHelper" ); + log << MSG::WARNING << "initialize_from_dictionary - unable to find preshower region index: id, reg " + << (std::string)id << " " << m_preshower_region_index + << endmsg; + } + else { + std::cout << "FaserDetectorIDHelper::initialize_from_dictionary - Warning: unable to find preshower region index: id, reg " + << (std::string)id << " " << m_preshower_region_index + << std::endl; + } + } + + // Save index to a MUON region for unpacking + id = faser_id.muon_exp(); + if (dict->find_region(id, m_muon_region_index)) { + if(m_msgSvc) { + MsgStream log(m_msgSvc, "FaserDetectorIDHelper" ); + log << MSG::WARNING << "initialize_from_dictionary - unable to find muon region index: id, reg " + << (std::string)id << " " << m_muon_region_index + << endmsg; } - //} + else { + std::cout << "FaserDetectorIDHelper::initialize_from_dictionary - Warning: unable to find muon region index: id, reg " + << (std::string)id << " " << m_muon_region_index + << std::endl; + } + } + } dict = dict_mgr.find_dictionary ("Tracker"); @@ -197,21 +230,38 @@ FaserDetectorIDHelper::initialize_from_dictionary(const IdDictMgr& dict_mgr) } } else { - // Save index to an ECAL region for unpacking - id = faser_id.ecal_exp(); - if (dict->find_region(id, m_ecal_region_index)) { - if(m_msgSvc) { - MsgStream log(m_msgSvc, "FaserDetectorIDHelper" ); - log << MSG::WARNING << "initialize_from_dictionary - unable to find ecal region index: id, reg " - << (std::string)id << " " << m_ecal_region_index - << endmsg; - } - else { - std::cout << "FaserDetectorIDHelper::initialize_from_dictionary - Warning: unable to find ecal region index: id, reg " - << (std::string)id << " " << m_ecal_region_index - << std::endl; - } - } + // Save index to an ECAL region for unpacking + id = faser_id.ecal_exp(); + if (dict->find_region(id, m_ecal_region_index)) { + if(m_msgSvc) { + MsgStream log(m_msgSvc, "FaserDetectorIDHelper" ); + log << MSG::WARNING << "initialize_from_dictionary - unable to find ecal region index: id, reg " + << (std::string)id << " " << m_ecal_region_index + << endmsg; + } + else { + std::cout << "FaserDetectorIDHelper::initialize_from_dictionary - Warning: unable to find ecal region index: id, reg " + << (std::string)id << " " << m_ecal_region_index + << std::endl; + } + } + + // Save index to an CALONU region for unpacking + id = faser_id.calonu_exp(); + if (dict->find_region(id, m_calonu_region_index)) { + if(m_msgSvc) { + MsgStream log(m_msgSvc, "FaserDetectorIDHelper" ); + log << MSG::WARNING << "initialize_from_dictionary - unable to find calonu region index: id, reg " + << (std::string)id << " " << m_calonu_region_index + << endmsg; + } + else { + std::cout << "FaserDetectorIDHelper::initialize_from_dictionary - Warning: unable to find calonu region index: id, reg " + << (std::string)id << " " << m_calonu_region_index + << std::endl; + } + } + } return (0); diff --git a/DetectorDescription/FaserDetDescr/src/FaserDetectorIDHelper.h b/DetectorDescription/FaserDetDescr/src/FaserDetectorIDHelper.h index ead07e481e66177d74b0ac9bf5f2ca71fc8de857..11d02fa9e3de91a8db14bd17c465347f2e3ff87b 100644 --- a/DetectorDescription/FaserDetDescr/src/FaserDetectorIDHelper.h +++ b/DetectorDescription/FaserDetDescr/src/FaserDetectorIDHelper.h @@ -47,10 +47,13 @@ public: size_type emulsion_region_index(); size_type veto_region_index(); + size_type vetonu_region_index(); size_type trigger_region_index(); size_type preshower_region_index(); + size_type muon_region_index(); size_type sct_region_index(); size_type ecal_region_index(); + size_type calonu_region_index(); void setMsgSvc(IMessageSvc* msgSvc) { m_msgSvc = msgSvc; } @@ -62,10 +65,14 @@ private: bool m_isSLHC; size_type m_emulsion_region_index; size_type m_veto_region_index; + size_type m_vetonu_region_index; size_type m_trigger_region_index; size_type m_preshower_region_index; + size_type m_muon_region_index; + size_type m_sct_region_index; size_type m_ecal_region_index; + size_type m_calonu_region_index; bool m_initialized; /// pointer to the message service IMessageSvc* m_msgSvc; @@ -82,17 +89,26 @@ inline FaserDetectorIDHelper::size_type FaserDetectorIDHelper::emulsion_region inline FaserDetectorIDHelper::size_type FaserDetectorIDHelper::veto_region_index() {return (m_veto_region_index);} +inline FaserDetectorIDHelper::size_type FaserDetectorIDHelper::vetonu_region_index() +{return (m_vetonu_region_index);} + inline FaserDetectorIDHelper::size_type FaserDetectorIDHelper::trigger_region_index() {return (m_trigger_region_index);} inline FaserDetectorIDHelper::size_type FaserDetectorIDHelper::preshower_region_index() {return (m_preshower_region_index);} +inline FaserDetectorIDHelper::size_type FaserDetectorIDHelper::muon_region_index() +{return (m_muon_region_index);} + inline FaserDetectorIDHelper::size_type FaserDetectorIDHelper::sct_region_index() {return (m_sct_region_index);} inline FaserDetectorIDHelper::size_type FaserDetectorIDHelper::ecal_region_index() {return (m_ecal_region_index);} +inline FaserDetectorIDHelper::size_type FaserDetectorIDHelper::calonu_region_index() +{return (m_calonu_region_index);} + #endif // SRC_FASERDETECTORIDHELPER_H diff --git a/Event/FaserByteStreamCnvSvcBase/python/FaserByteStreamCnvSvcBaseConfig.py b/Event/FaserByteStreamCnvSvcBase/python/FaserByteStreamCnvSvcBaseConfig.py index 0762f26a32509e0dd8c0f565d58d46baad9f64d8..971cbb02381db9add998e9feaa08c3efd234ff4e 100644 --- a/Event/FaserByteStreamCnvSvcBase/python/FaserByteStreamCnvSvcBaseConfig.py +++ b/Event/FaserByteStreamCnvSvcBase/python/FaserByteStreamCnvSvcBaseConfig.py @@ -15,10 +15,12 @@ def FaserByteStreamCnvSvcBaseCfg(flags, **kwargs): adxProvider.TypeNames += [ "RawWaveformContainer/CaloWaveforms", "RawWaveformContainer/Calo2Waveforms", + "RawWaveformContainer/CaloNuWaveforms", "RawWaveformContainer/VetoWaveforms", "RawWaveformContainer/VetoNuWaveforms", "RawWaveformContainer/TriggerWaveforms", "RawWaveformContainer/PreshowerWaveforms", + "RawWaveformContainer/MuonWaveforms", "RawWaveformContainer/ClockWaveforms", "RawWaveformContainer/TestWaveforms" ] diff --git a/LHCData/LHCDataAlgs/src/LHCDataAlg.cxx b/LHCData/LHCDataAlgs/src/LHCDataAlg.cxx index 1c0e49926225f2198d0ad6c8c4447a3bd966a628..0799eb393c187b4df1c9a0b0fb6522653c1d010a 100644 --- a/LHCData/LHCDataAlgs/src/LHCDataAlg.cxx +++ b/LHCData/LHCDataAlgs/src/LHCDataAlg.cxx @@ -82,6 +82,9 @@ LHCDataAlg::execute(const EventContext& ctx) const { if (m_lhcTool->getBeam1Bunches(ctx) == 0) { ATH_MSG_INFO("No beam 1 bunches, can't set nearest"); nearest = -3564; + } else if (m_lhcTool->getBeam1Bunches(ctx) <= m_lhcTool->getCollidingBunches(ctx)) { + ATH_MSG_INFO("No unpaired beam 1 bunches, " << m_lhcTool->getCollidingBunches(ctx) << " colliding, can't set nearest unpaired"); + nearest = -3564; } else { nearest = findNearest(bcid, bcid_mask, 1); // Beam1 unpaired } @@ -92,6 +95,9 @@ LHCDataAlg::execute(const EventContext& ctx) const { if (m_lhcTool->getBeam2Bunches(ctx) == 0) { ATH_MSG_INFO("No beam 2 bunches, can't set nearest"); nearest = -3564; + } else if (m_lhcTool->getBeam2Bunches(ctx) <= m_lhcTool->getCollidingBunches(ctx)) { + ATH_MSG_INFO("No unpaired beam 2 bunches, " << m_lhcTool->getCollidingBunches(ctx) << " colliding, can't set nearest unpaired"); + nearest = -3564; } else { nearest = findNearest(bcid, bcid_mask, 2); // Beam2 unpaired } @@ -101,8 +107,12 @@ LHCDataAlg::execute(const EventContext& ctx) const { // Add 127 to current BCID to check if inbound B1 is nearby FASER if (m_lhcTool->getBeam1Bunches(ctx) == 0) { - ATH_MSG_INFO("No beam 1 bunches, can't set nearest"); + ATH_MSG_INFO("No beam 1 bunches, can't set nearest inbound"); nearest = -3564; + } else if (m_lhcTool->getBeam1Bunches(ctx) <= m_lhcTool->getCollidingBunches(ctx)) { + // No unpaired B1 + int offset_bcid = (bcid + 127) % 3564; + nearest = findNearest(offset_bcid, bcid_mask, 3); // Inbound B1 } else { int offset_bcid = (bcid + 127) % 3564; nearest = findNearest(offset_bcid, bcid_mask, 1); // Inbound B1 @@ -115,7 +125,7 @@ LHCDataAlg::execute(const EventContext& ctx) const { unsigned int previous; if (m_lhcTool->getCollidingBunches(ctx) == 0) { - ATH_MSG_INFO("No colliding bunches, can't set nearest"); + ATH_MSG_INFO("No colliding bunches, can't set previous colliding"); previous = 9999; } else { previous = previousColliding(bcid, bcid_mask); @@ -125,7 +135,7 @@ LHCDataAlg::execute(const EventContext& ctx) const { << " to the previous colliding bunch "); if (m_lhcTool->getCollidingBunches(ctx) == 0) { - ATH_MSG_INFO("No colliding bunches, can't set nearest"); + ATH_MSG_INFO("No colliding bunches, can't set start of train"); previous = 9999; } else { previous = previousTrain(bcid, bcid_mask); diff --git a/PhysicsAnalysis/NtupleDumper/CMakeLists.txt b/PhysicsAnalysis/NtupleDumper/CMakeLists.txt index 56d8fd54b7983d5725af044dd365b39a551920cb..359fe29b29ca0a4156289ef2f416b80ee499a407 100644 --- a/PhysicsAnalysis/NtupleDumper/CMakeLists.txt +++ b/PhysicsAnalysis/NtupleDumper/CMakeLists.txt @@ -8,7 +8,7 @@ atlas_add_component( src/NtupleDumperAlg.cxx src/component/NtupleDumper_entries.cxx - LINK_LIBRARIES AthenaBaseComps StoreGateLib xAODFaserWaveform xAODFaserCalorimeter xAODFaserTrigger xAODFaserLHC ScintIdentifier FaserCaloIdentifier GeneratorObjects FaserActsGeometryLib TrackerSimEvent TrackerSimData TrackerIdentifier TrackerReadoutGeometry TrkTrack GeoPrimitives TrackerRIO_OnTrack TrackerSpacePoint FaserActsKalmanFilterLib AtlasHepMCLib WaveformConditionsToolsLib FaserActsmanVertexingLib + LINK_LIBRARIES AthenaBaseComps StoreGateLib xAODFaserWaveform xAODFaserCalorimeter xAODFaserTrigger xAODFaserLHC ScintIdentifier FaserCaloIdentifier GeneratorObjects FaserActsGeometryLib TrackerSimEvent TrackerSimData TrackerIdentifier ScintIdentifier TrackerReadoutGeometry TrkTrack GeoPrimitives TrackerRIO_OnTrack TrackerSpacePoint FaserActsKalmanFilterLib AtlasHepMCLib WaveformConditionsToolsLib FaserActsmanVertexingLib PRIVATE_LINK_LIBRARIES nlohmann_json::nlohmann_json ) atlas_install_python_modules( python/*.py ) diff --git a/PhysicsAnalysis/NtupleDumper/scripts/faser_ntuple_maker.py b/PhysicsAnalysis/NtupleDumper/scripts/faser_ntuple_maker.py index 3f28a5782da238b899812baad6a3dc13aa2b2853..c9e7b70454ab19afea4dd908e4c24ea180da441a 100755 --- a/PhysicsAnalysis/NtupleDumper/scripts/faser_ntuple_maker.py +++ b/PhysicsAnalysis/NtupleDumper/scripts/faser_ntuple_maker.py @@ -46,9 +46,11 @@ parser.add_argument("--partial", action='store_true', help="Allow partial input files") parser.add_argument("-c", "--cond", default="", - help="Specify global conditions tag (default: OFLCOND-FASER-04)") + help="Specify global conditions tag (default: OFLCOND-FASER-05)") parser.add_argument("--backward", action='store_true', help="Use backward CKF tracks (default: forward)") +parser.add_argument("--useIFT", action='store_true', + help="Use 4-station tracks (default: 3-station)") parser.add_argument("--trigFilt", action='store_true', help="apply trigger event filter") @@ -232,6 +234,7 @@ print(f"Blind = {not args.unblind}") print(f"OnlyBlinded = {args.onlyblind}") print(f"Stable Beams = {not args.no_stable}") print(f"Backward = {args.backward}") +print(f"Use IFT = {args.useIFT}") print(f"GRL = {args.grl}") print(f"Random Filter = {args.randomTrigFilt}") print(f"Random Only Filter = {args.randomOnlyTrigFilt}") @@ -262,7 +265,7 @@ else: if runtype in ["TI12Data04", "TI12MC04"]: configFlags.GeoModel.FaserVersion = "FASERNU-04" # FASER geometry - configFlags.IOVDb.GlobalTag = "OFLCOND-FASER-04" + configFlags.IOVDb.GlobalTag = "OFLCOND-FASER-05" elif runtype == "TI12Data03": configFlags.GeoModel.FaserVersion = "FASERNU-03" # FASER geometry @@ -317,9 +320,16 @@ if args.fluka: if args.backward: if args.isMC: mc_kwargs['TrackCollectionWithoutIFT'] = "CKFTrackCollectionBackwardWithoutIFT" + mc_kwargs['TrackCollection'] = "CKFTrackCollectionBackward" else: grl_kwargs['TrackCollectionWithoutIFT'] = "CKFTrackCollectionBackwardWithoutIFT" + grl_kwargs['TrackCollection'] = "CKFTrackCollectionBackward" +if args.isMC: + mc_kwargs['UseIFT'] = args.useIFT +else: + grl_kwargs['UseIFT'] = args.useIFT + # algorithm from NtupleDumper.NtupleDumperConfig import NtupleDumperAlgCfg if args.isMC: diff --git a/PhysicsAnalysis/NtupleDumper/scripts/submit_faser_ntuple_maker.sh b/PhysicsAnalysis/NtupleDumper/scripts/submit_faser_ntuple_maker.sh index ae925ed988f5d668c256f55195389b3668a74838..97022aeef8a3402a51a7062ea1497f8d1e2686f5 100755 --- a/PhysicsAnalysis/NtupleDumper/scripts/submit_faser_ntuple_maker.sh +++ b/PhysicsAnalysis/NtupleDumper/scripts/submit_faser_ntuple_maker.sh @@ -265,6 +265,19 @@ else cp -r $cond_directory . ls -R data fi +# +# Further check if there is a pool conditions override +if [[ -d "data/poolcond" ]]; then + echo "Local POOL directory found!" + echo "Change ATLAS_POOLCOND_PATH" + echo " from $ATLAS_POOLCOND_PATH" + export ATLAS_POOLCOND_PATH=`pwd -P`/data + echo " to $ATLAS_POOLCOND_PATH" +else + echo "No local pool files found, use default:" + echo " $ATLAS_POOLCOND_PATH" +fi +echo "Final ATLAS_POOLCOND_PATH: $ATLAS_POOLCOND_PATH" # # Run job # diff --git a/PhysicsAnalysis/NtupleDumper/src/NtupleDumperAlg.cxx b/PhysicsAnalysis/NtupleDumper/src/NtupleDumperAlg.cxx index 284cf59e713f1b61b12196b6d48eda70ea2a30e6..05e31bc208ad3c0a4f1492250e98cfa2c548f7c1 100644 --- a/PhysicsAnalysis/NtupleDumper/src/NtupleDumperAlg.cxx +++ b/PhysicsAnalysis/NtupleDumper/src/NtupleDumperAlg.cxx @@ -47,9 +47,12 @@ void NtupleDumperAlg::addBranch(const std::string &name, m_tree->Branch(name.c_str(),var,(name+"/I").c_str()); } +// Return channel map from mappingTool std::map<std::string, std::list<int>>& NtupleDumperAlg::getChannelMap() const { + ATH_MSG_DEBUG("getChannelMap"); + // Use waveform map to find all defined waveform channels auto mapping = m_mappingTool->getCableMapping(); ATH_MSG_DEBUG("Cable mapping contains " << mapping.size() << " entries"); @@ -58,15 +61,23 @@ NtupleDumperAlg::getChannelMap() const { // use this to fill my own map of channel lists keyed by type static std::map<std::string, std::list<int>> wave_map; + std::string detector; + for (const auto& [key, value] : mapping) { - wave_map[value.first].push_back(key); - ATH_MSG_DEBUG("Found mapping " << value.first << " chan " << key); + // Special handling for Veto to differentiate veto1 from veto2 + detector = value.first; + if (value.first == std::string("veto")) { + // Append station to key string + detector += std::to_string(m_vetoID->station(value.second)+1); + } + wave_map[detector].push_back(key); + ATH_MSG_DEBUG("Found mapping " << detector << " chan " << key); } return wave_map; } -// Have to declare this cost to call during execute +// Have to declare this const to call during execute void NtupleDumperAlg::defineWaveBranches() const { ATH_MSG_DEBUG("defineWaveBranches called"); @@ -78,17 +89,30 @@ void NtupleDumperAlg::defineWaveBranches() const { for (const auto& [key, value] : wave_map) { if (key == std::string("calo")) { - addWaveBranches("CaloLo", value); + m_calolo_channels = value; + // Figure out ntuple below } else if (key == std::string("calo2")) { - addWaveBranches("CaloHi", value); + m_calohi_channels = value; + // Figure out ntuple below } else if (key == std::string("calonu")) { + m_calonu_channels = value; addWaveBranches("CaloNu", value); + addCalibratedBranches("CaloNu", value); + addCaloSumBranches("CaloNu"); } + // Old way (depends on cable map order) else if (key == std::string("veto")) { addWaveBranches("Veto", value); } + // New way (better, differentiates veto1 and veto2 + else if (key == std::string("veto1")) { + addWaveBranches("Veto1", value); + } + else if (key == std::string("veto2")) { + addWaveBranches("Veto2", value); + } else if (key == std::string("vetonu")) { addWaveBranches("VetoNu", value); } @@ -97,6 +121,12 @@ void NtupleDumperAlg::defineWaveBranches() const { } else if (key == std::string("preshower")) { addWaveBranches("Preshower", value); + addCalibratedBranches("Preshower", value); + addBranch("Preshower_total_nMIP", &m_preshower_total_nMIP); + addBranch("Preshower_total_E_dep", &m_preshower_total_E_dep); + } + else if (key == std::string("muon")) { + addWaveBranches("Muon", value); } else if (key == std::string("clock")) { // ignore this @@ -107,35 +137,88 @@ void NtupleDumperAlg::defineWaveBranches() const { else { ATH_MSG_WARNING("Found unknown mapping type " << key); } + } // End of loop over wave_map entries + + // Figure out calorimeter + if (m_calolo_channels.size() && !m_calohi_channels.size()) { + // Only "calo" type found, 2022/23 configuration + ATH_MSG_INFO("defineWaveBranches found " << m_calolo_channels.size() << " calo channels => 2022/23 configuration"); + m_dual_gain = false; + m_calo_channels = m_calolo_channels; + m_calolo_channels.clear(); + addWaveBranches("Calo", m_calo_channels); + addCalibratedBranches("Calo", m_calo_channels); + addCaloSumBranches("Calo"); } - + else if (m_calolo_channels.size() && m_calohi_channels.size()) { + // Both found, 2024/25 configuration (both defined) + ATH_MSG_INFO("defineWaveBranches found " << m_calolo_channels.size() << " calo and " << m_calohi_channels.size() << " calo2 channels => 2024/25 configuration"); + m_dual_gain = true; + addWaveBranches("CaloLo", m_calolo_channels); + addWaveBranches("CaloHi", m_calohi_channels); + addCalibratedBranches("CaloLo", m_calolo_channels); + addCalibratedBranches("CaloHi", m_calohi_channels); + addCaloSumBranches("CaloLo"); + addCaloSumBranches("CaloHi"); + } + else { + // Unknown configuration + ATH_MSG_WARNING("defineWaveBranches found " << m_calolo_channels.size() << " calo channels and " << m_calohi_channels.size() << " calo2 channels!"); + m_dual_gain = false; + return; + } + ATH_MSG_DEBUG("defineWaveBranches done"); - } -void NtupleDumperAlg::addWaveBranches(const std::string &name, - int nchannels, - int first) const { - for(int ch=0;ch<nchannels;ch++) { - std::string base=name+std::to_string(ch)+"_"; - addBranch(base+"time",&m_wave_localtime[first]); - addBranch(base+"peak",&m_wave_peak[first]); - addBranch(base+"width",&m_wave_width[first]); - addBranch(base+"charge",&m_wave_charge[first]); - addBranch(base+"raw_peak",&m_wave_raw_peak[first]); - addBranch(base+"raw_charge",&m_wave_raw_charge[first]); - addBranch(base+"baseline",&m_wave_baseline_mean[first]); - addBranch(base+"baseline_rms",&m_wave_baseline_rms[first]); - addBranch(base+"status",&m_wave_status[first]); - first++; +void +NtupleDumperAlg::addCaloSumBranches(const std::string &name) const { + + ATH_MSG_DEBUG("addCaloSumBranches " << name << " called"); + + // Utility to define the calorimeter sum branches + if (name == std::string("Calo")) { + addBranch("Calo_total_nMIP", &m_calo_total_nMIP); + addBranch("Calo_total_E_dep", &m_calo_total_E_dep); + addBranch("Calo_total_fit_E_EM", &m_calo_total_fit_E_EM); + addBranch("Calo_total_raw_E_EM", &m_calo_total_raw_E_EM); + addBranch("Calo_total_E_EM", &m_calo_total_E_EM); + + addBranch("Calo_total_fit_E_EM_fudged", &m_calo_total_fit_E_EM_fudged); + addBranch("Calo_total_raw_E_EM_fudged", &m_calo_total_raw_E_EM_fudged); + addBranch("Calo_total_E_EM_fudged", &m_calo_total_E_EM_fudged); + } + else if (name == std::string("CaloLo")) { + addBranch("CaloLo_total_nMIP", &m_calolo_total_nMIP); + addBranch("CaloLo_total_E_dep", &m_calolo_total_E_dep); + addBranch("CaloLo_total_fit_E_EM", &m_calolo_total_fit_E_EM); + addBranch("CaloLo_total_raw_E_EM", &m_calolo_total_raw_E_EM); + addBranch("CaloLo_total_E_EM", &m_calolo_total_E_EM); + } + else if (name == std::string("CaloHi")) { + addBranch("CaloHi_total_nMIP", &m_calohi_total_nMIP); + addBranch("CaloHi_total_E_dep", &m_calohi_total_E_dep); + addBranch("CaloHi_total_fit_E_EM", &m_calohi_total_fit_E_EM); + addBranch("CaloHi_total_raw_E_EM", &m_calohi_total_raw_E_EM); + addBranch("CaloHi_total_E_EM", &m_calohi_total_E_EM); } + else if (name == std::string("CaloNu")) { + addBranch("CaloNu_total_nMIP", &m_calonu_total_nMIP); + addBranch("CaloNu_total_E_dep", &m_calonu_total_E_dep); + addBranch("CaloNu_total_fit_E_EM", &m_calonu_total_fit_E_EM); + addBranch("CaloNu_total_raw_E_EM", &m_calonu_total_raw_E_EM); + addBranch("CaloNu_total_E_EM", &m_calonu_total_E_EM); + } + else { + ATH_MSG_WARNING("addCaloSumBranches - Unknown type " << name << "!"); + } } // Use channel list to add branches void NtupleDumperAlg::addWaveBranches(const std::string &name, std::list<int> channel_list) const { - ATH_MSG_DEBUG("Adding " << name << " with channels " << channel_list); + ATH_MSG_DEBUG("Adding waveforms " << name << " with channels " << channel_list); int nchannels = channel_list.size(); for(int i=0;i<nchannels;i++) { @@ -192,17 +275,25 @@ void NtupleDumperAlg::FillWaveBranches(const xAOD::WaveformHitContainer &wave, b } void NtupleDumperAlg::addCalibratedBranches(const std::string &name, - int nchannels, - int first) { - for(int ch=0;ch<nchannels;ch++) { - std::string base=name+std::to_string(ch)+"_"; - addBranch(base+"nMIP",&m_calibrated_nMIP[first]); - addBranch(base+"E_dep",&m_calibrated_E_dep[first]); - addBranch(base+"E_EM",&m_calibrated_E_EM[first]); - first++; + std::list<int> channel_list) const { + + ATH_MSG_DEBUG("Adding calibrated " << name << " with channels " << channel_list); + + int nchannels = channel_list.size(); + for(int i=0;i<nchannels;i++) { + int ch = channel_list.front(); + channel_list.pop_front(); + + std::string base=name+std::to_string(i); + addBranch(base+"_nMIP", &m_calibrated_nMIP[ch]); + addBranch(base+"_E_dep",&m_calibrated_E_dep[ch]); + addBranch(base+"_E_EM", &m_calibrated_E_EM[ch]); + ATH_MSG_DEBUG("Added " << base << " ch " << ch); + } } + StatusCode NtupleDumperAlg::initialize() { @@ -217,10 +308,12 @@ StatusCode NtupleDumperAlg::initialize() ATH_CHECK(m_trackSegmentCollection.initialize()); ATH_CHECK(m_trackTrueSegmentCollection.initialize()); - ATH_CHECK(m_vetoNuContainer.initialize()); ATH_CHECK(m_vetoContainer.initialize()); + ATH_CHECK(m_vetoNuContainer.initialize()); ATH_CHECK(m_triggerContainer.initialize()); ATH_CHECK(m_preshowerContainer.initialize()); + ATH_CHECK(m_muonContainer.initialize()); + ATH_CHECK(m_ecalContainer.initialize()); ATH_CHECK(m_ecal2Container.initialize()); ATH_CHECK(m_caloNuContainer.initialize()); @@ -237,8 +330,11 @@ StatusCode NtupleDumperAlg::initialize() ATH_CHECK(m_eventInfoKey.initialize()); ATH_CHECK(detStore()->retrieve(m_sctHelper, "FaserSCT_ID")); - + ATH_CHECK(detStore()->retrieve(m_detMgr, "SCT")); + + ATH_CHECK(detStore()->retrieve(m_vetoID, "VetoID")); + ATH_CHECK(m_extrapolationTool.retrieve()); ATH_CHECK(m_trackingGeometryTool.retrieve()); ATH_CHECK(m_trackTruthMatchingTool.retrieve()); @@ -305,19 +401,6 @@ StatusCode NtupleDumperAlg::initialize() m_tree->Branch("ScintHit", &m_scintHit); - addCalibratedBranches("Calo",4,0); - addBranch("Calo_total_nMIP", &m_calo_total_nMIP); - addBranch("Calo_total_E_dep", &m_calo_total_E_dep); - addBranch("Calo_total_fit_E_EM", &m_calo_total_fit_E_EM); - addBranch("Calo_total_raw_E_EM", &m_calo_total_raw_E_EM); - addBranch("Calo_total_E_EM", &m_calo_total_E_EM); - addBranch("Calo_total_fit_E_EM_fudged", &m_calo_total_fit_E_EM_fudged); - addBranch("Calo_total_raw_E_EM_fudged", &m_calo_total_raw_E_EM_fudged); - addBranch("Calo_total_E_EM_fudged", &m_calo_total_E_EM_fudged); - - addCalibratedBranches("Preshower",2,12); - addBranch("Preshower_total_nMIP", &m_preshower_total_nMIP); - addBranch("Preshower_total_E_dep", &m_preshower_total_E_dep); //TRACKER addBranch("nClusters0",&m_station0Clusters); @@ -340,7 +423,7 @@ StatusCode NtupleDumperAlg::initialize() m_tree->Branch("TrackSegment_py", &m_trackseg_py); m_tree->Branch("TrackSegment_pz", &m_trackseg_pz); - addBranch("TrueTrackSegments",&m_nTruetracksegs); + addBranch("TrueTrackSegments",&m_nTruetracksegs); m_tree->Branch("TrueTrackSegment_Chi2", &m_Truetrackseg_Chi2); m_tree->Branch("TrueTrackSegment_nDoF", &m_Truetrackseg_DoF); m_tree->Branch("TrueTrackSegment_x", &m_Truetrackseg_x); @@ -715,6 +798,11 @@ StatusCode NtupleDumperAlg::execute(const EventContext &ctx) const FillWaveBranches(*preshowerContainer, isMC); } + SG::ReadHandle<xAOD::WaveformHitContainer> muonContainer { m_muonContainer, ctx }; + if (muonContainer.isValid()) { + FillWaveBranches(*muonContainer, isMC); + } + SG::ReadHandle<xAOD::WaveformHitContainer> ecalContainer { m_ecalContainer, ctx }; if (ecalContainer.isValid()) { FillWaveBranches(*ecalContainer, isMC); @@ -762,26 +850,24 @@ StatusCode NtupleDumperAlg::execute(const EventContext &ctx) const return StatusCode::SUCCESS; } } + if (m_doRandomFilter) { - bool trig_random = m_tap & 16; - if ( !(trig_random)) { + bool trig_random = m_tap & 16; + if ( !(trig_random)) { // don't process events that fail to activate random trigger ATH_MSG_DEBUG("event did not pass random trigger filter"); return StatusCode::SUCCESS; } + } - } - - if (m_doRandomOnlyFilter) { - bool trig_random = m_tap == 16; - if ( !(trig_random)) { + if (m_doRandomOnlyFilter) { + bool trig_random = m_tap == 16; + if ( !(trig_random)) { // don't process events that fail to activate random only trigger ATH_MSG_DEBUG("event did not pass random trigger filter"); return StatusCode::SUCCESS; - } - - } - + } + } if (m_doScintFilter) { // Get channel mapping @@ -824,6 +910,13 @@ StatusCode NtupleDumperAlg::execute(const EventContext &ctx) const vetoSt1_trig &= m_wave_raw_peak[chan] > 25.0; } } + } else if (wave_map.contains(std::string("veto1"))) { + for (auto chan : wave_map[std::string("veto1")]) { + vetoSt1_trig &= m_wave_raw_peak[chan] > 25.0; + } + for (auto chan : wave_map[std::string("veto2")]) { + vetoSt2_trig &= m_wave_raw_peak[chan] > 25.0; + } } else { vetoSt1_trig = false; vetoSt2_trig = false; @@ -920,30 +1013,33 @@ StatusCode NtupleDumperAlg::execute(const EventContext &ctx) const } // done with processing only on real data // fill scintHit word with bits that reflect if a scintillator was hit (1 = vetoNu0, 2 = vetoNu1, 4 = vetoSt1_1, 8 vetoSt2_0, 16 = vetoSt2_1, 32 = Timing scint, 64 = preshower0, 128 = preshower1) - if (m_wave_raw_charge[4] > 40.0) { - m_scintHit = m_scintHit | 1; - } - if (m_wave_raw_charge[5] > 40.0) { - m_scintHit = m_scintHit | 2; - } - if (m_wave_raw_charge[14] > 40.0) { - m_scintHit = m_scintHit | 4; - } - if (m_wave_raw_charge[6] > 40.0) { - m_scintHit = m_scintHit | 8; - } - if (m_wave_raw_charge[7] > 40.0) { - m_scintHit = m_scintHit | 16; - } - if (m_wave_raw_charge[8]+m_wave_raw_charge[9]+m_wave_raw_charge[10]+m_wave_raw_charge[11] > 25.0) { - m_scintHit = m_scintHit | 32; - } - if (m_wave_raw_charge[12] > 2.5) { - m_scintHit = m_scintHit | 64; - } - if (m_wave_raw_charge[13] > 2.5) { - m_scintHit = m_scintHit | 128; - } + + // This either needs to be updated to use cable map, or skipped + // Skip for now + // if (m_wave_raw_charge[4] > 40.0) { + // m_scintHit = m_scintHit | 1; + // } + // if (m_wave_raw_charge[5] > 40.0) { + // m_scintHit = m_scintHit | 2; + // } + // if (m_wave_raw_charge[14] > 40.0) { + // m_scintHit = m_scintHit | 4; + // } + // if (m_wave_raw_charge[6] > 40.0) { + // m_scintHit = m_scintHit | 8; + // } + // if (m_wave_raw_charge[7] > 40.0) { + // m_scintHit = m_scintHit | 16; + // } + // if (m_wave_raw_charge[8]+m_wave_raw_charge[9]+m_wave_raw_charge[10]+m_wave_raw_charge[11] > 25.0) { + // m_scintHit = m_scintHit | 32; + // } + // if (m_wave_raw_charge[12] > 2.5) { + // m_scintHit = m_scintHit | 64; + // } + // if (m_wave_raw_charge[13] > 2.5) { + // m_scintHit = m_scintHit | 128; + // } if (isMC) { // if simulation find MC cross section and primary lepton // Work out effective cross section for MC @@ -1085,25 +1181,56 @@ StatusCode NtupleDumperAlg::execute(const EventContext &ctx) const // load in calibrated calo container SG::ReadHandle<xAOD::CalorimeterHitContainer> ecalCalibratedContainer { m_ecalCalibratedContainer, ctx }; - ATH_CHECK(ecalCalibratedContainer.isValid()); - for (auto hit : *ecalCalibratedContainer) { - int ch=hit->channel(); - m_calibrated_nMIP[ch] = hit->Nmip(); - m_calibrated_E_dep[ch] = hit->E_dep(); - m_calibrated_E_EM[ch] = hit->E_EM(); - - m_calo_total_nMIP += hit->Nmip(); - m_calo_total_E_dep += hit->E_dep(); - m_calo_total_fit_E_EM += hit->E_EM(); - m_calo_total_raw_E_EM += (hit->E_EM()*hit->fit_to_raw_ratio()); - - if (m_wave_status[ch]&4) { - m_calo_total_E_EM += hit->E_EM(); - } else { - m_calo_total_E_EM += (hit->E_EM()*hit->fit_to_raw_ratio()); - } + if (ecalCalibratedContainer.isValid()) { + for (auto hit : *ecalCalibratedContainer) { + int ch=hit->channel(); + m_calibrated_nMIP[ch] = hit->Nmip(); + m_calibrated_E_dep[ch] = hit->E_dep(); + m_calibrated_E_EM[ch] = hit->E_EM(); + + ATH_MSG_DEBUG("Calibrated calo: ch is " << ch + << ", edep is " << hit->E_dep() + << ", E_EM is " << hit->E_EM() + << ", Nmip is " << hit->Nmip() + << ", fit_to_raw_ratio is " << hit->fit_to_raw_ratio()); + + if (m_dual_gain) { + m_calolo_total_nMIP += hit->Nmip(); + m_calolo_total_E_dep += hit->E_dep(); + m_calolo_total_fit_E_EM += hit->E_EM(); + m_calolo_total_raw_E_EM += (hit->E_EM()*hit->fit_to_raw_ratio()); + + if (m_wave_status[ch]&4) { // Overflows + m_calolo_total_E_EM += hit->E_EM(); + } else { + m_calolo_total_E_EM += (hit->E_EM()*hit->fit_to_raw_ratio()); + } + } else { + m_calo_total_nMIP += hit->Nmip(); + m_calo_total_E_dep += hit->E_dep(); + m_calo_total_fit_E_EM += hit->E_EM(); + m_calo_total_raw_E_EM += (hit->E_EM()*hit->fit_to_raw_ratio()); + + if (m_wave_status[ch]&4) { // Overflows + m_calo_total_E_EM += hit->E_EM(); + } else { + m_calo_total_E_EM += (hit->E_EM()*hit->fit_to_raw_ratio()); + } - ATH_MSG_DEBUG("Calibrated calo: ch is " << ch << ", edep is " << hit->E_dep() << ", E_EM is " << hit->E_EM() << ", Nmip is " << hit->Nmip() << ", fit_to_raw_ratio is " << hit->fit_to_raw_ratio()); + // add a fudged energy variable that corrects the MC to agree with the testbeam results + if (isMC) { + // Add fudge factor for MC + m_calo_total_fit_E_EM_fudged = m_calo_total_fit_E_EM * m_caloMC_FudgeFactor; + m_calo_total_raw_E_EM_fudged = m_calo_total_raw_E_EM * m_caloMC_FudgeFactor; + m_calo_total_E_EM_fudged = m_calo_total_E_EM * m_caloMC_FudgeFactor; + } else { + // Unchanged in data + m_calo_total_fit_E_EM_fudged = m_calo_total_fit_E_EM; + m_calo_total_raw_E_EM_fudged = m_calo_total_raw_E_EM; + m_calo_total_E_EM_fudged = m_calo_total_E_EM; + } + } + } //// the following is an example of how to access the linked waveform data from the calibrated data //auto measurements = &(hit->WaveformLinks())[0]; @@ -1117,32 +1244,80 @@ StatusCode NtupleDumperAlg::execute(const EventContext &ctx) const //} } - // add a fudged energy variable that corrects the MC to agree with the testbeam results - m_calo_total_fit_E_EM_fudged = m_calo_total_fit_E_EM; - m_calo_total_raw_E_EM_fudged = m_calo_total_raw_E_EM; - m_calo_total_E_EM_fudged = m_calo_total_E_EM; - if (isMC) { - m_calo_total_fit_E_EM_fudged = m_calo_total_fit_E_EM_fudged * m_caloMC_FudgeFactor; - m_calo_total_raw_E_EM_fudged = m_calo_total_raw_E_EM_fudged * m_caloMC_FudgeFactor; - m_calo_total_E_EM_fudged = m_calo_total_E_EM_fudged * m_caloMC_FudgeFactor; + // load in calibrated calo2 container + SG::ReadHandle<xAOD::CalorimeterHitContainer> ecal2CalibratedContainer { m_ecal2CalibratedContainer, ctx }; + if (ecal2CalibratedContainer.isValid()) { + for (auto hit : *ecal2CalibratedContainer) { + int ch=hit->channel(); + m_calibrated_nMIP[ch] = hit->Nmip(); + m_calibrated_E_dep[ch] = hit->E_dep(); + m_calibrated_E_EM[ch] = hit->E_EM(); + + ATH_MSG_DEBUG("Calibrated calo: ch is " << ch + << ", edep is " << hit->E_dep() + << ", E_EM is " << hit->E_EM() + << ", Nmip is " << hit->Nmip() + << ", fit_to_raw_ratio is " << hit->fit_to_raw_ratio()); + + m_calohi_total_nMIP += hit->Nmip(); + m_calohi_total_E_dep += hit->E_dep(); + m_calohi_total_fit_E_EM += hit->E_EM(); + m_calohi_total_raw_E_EM += (hit->E_EM()*hit->fit_to_raw_ratio()); + + if (m_wave_status[ch]&4) { // Overflows + m_calohi_total_E_EM += hit->E_EM(); + } else { + m_calohi_total_E_EM += (hit->E_EM()*hit->fit_to_raw_ratio()); + } + } } - + + // load in calibrated calo2 container + SG::ReadHandle<xAOD::CalorimeterHitContainer> calonuCalibratedContainer { m_calonuCalibratedContainer, ctx }; + if (calonuCalibratedContainer.isValid()) { + for (auto hit : *calonuCalibratedContainer) { + int ch=hit->channel(); + m_calibrated_nMIP[ch] = hit->Nmip(); + m_calibrated_E_dep[ch] = hit->E_dep(); + m_calibrated_E_EM[ch] = hit->E_EM(); + + ATH_MSG_DEBUG("Calibrated calo: ch is " << ch + << ", edep is " << hit->E_dep() + << ", E_EM is " << hit->E_EM() + << ", Nmip is " << hit->Nmip() + << ", fit_to_raw_ratio is " << hit->fit_to_raw_ratio()); + + m_calonu_total_nMIP += hit->Nmip(); + m_calonu_total_E_dep += hit->E_dep(); + m_calonu_total_fit_E_EM += hit->E_EM(); + m_calonu_total_raw_E_EM += (hit->E_EM()*hit->fit_to_raw_ratio()); + + if (m_wave_status[ch]&4) { // Overflows + m_calonu_total_E_EM += hit->E_EM(); + } else { + m_calonu_total_E_EM += (hit->E_EM()*hit->fit_to_raw_ratio()); + } + } + } + // load in calibrated preshower container SG::ReadHandle<xAOD::CalorimeterHitContainer> preshowerCalibratedContainer { m_preshowerCalibratedContainer, ctx }; - ATH_CHECK(preshowerCalibratedContainer.isValid()); - for (auto hit : *preshowerCalibratedContainer) { - int ch=hit->channel(); - m_calibrated_nMIP[ch] = hit->Nmip() * hit->fit_to_raw_ratio(); - m_calibrated_E_dep[ch] = hit->E_dep() * hit->fit_to_raw_ratio(); - - m_preshower_total_nMIP += hit->Nmip() * hit->fit_to_raw_ratio(); - m_preshower_total_E_dep += hit->E_dep() * hit->fit_to_raw_ratio(); - - ATH_MSG_DEBUG("Calibrated preshower: ch is " << ch << ", edep is " << hit->E_dep() << ", E_EM is " << hit->E_EM() << ", Nmip is " << hit->Nmip() << ", fit_to_raw_ratio is " << hit->fit_to_raw_ratio()); + if (preshowerCalibratedContainer.isValid()) { + for (auto hit : *preshowerCalibratedContainer) { + int ch=hit->channel(); + m_calibrated_nMIP[ch] = hit->Nmip() * hit->fit_to_raw_ratio(); + m_calibrated_E_dep[ch] = hit->E_dep() * hit->fit_to_raw_ratio(); + + m_preshower_total_nMIP += hit->Nmip() * hit->fit_to_raw_ratio(); + m_preshower_total_E_dep += hit->E_dep() * hit->fit_to_raw_ratio(); + + ATH_MSG_DEBUG("Calibrated preshower: ch is " << ch << ", edep is " << hit->E_dep() << ", E_EM is " << hit->E_EM() << ", Nmip is " << hit->Nmip() << ", fit_to_raw_ratio is " << hit->fit_to_raw_ratio()); + } } - + // enforce blinding such that events that miss the veto layers and have a large calo signal are skipped and not in the output root file // Only blind colliding BCIDs (+/- 1) + // This needs to be fixed!!! bool blinded_event = false; if ((!isMC) && abs(m_distanceToCollidingBCID) <= 1) { if (m_calo_total_E_EM > m_blindingCaloThreshold ) { // energy is in MeV @@ -1218,13 +1393,13 @@ StatusCode NtupleDumperAlg::execute(const EventContext &ctx) const } m_hitSet.push_back(hitSet.to_ulong()); if (stationMap.count(1) == 0 || stationMap.count(2) == 0 || stationMap.count(3) == 0) continue; - + const Trk::TrackParameters* upstreamParameters = track->trackParameters()->front(); const Trk::TrackParameters* downstreamParameters = track->trackParameters()->back(); if ((upstreamParameters == nullptr) || (downstreamParameters == nullptr)) continue; - m_nLayers.push_back(layerMap.size()); + m_nLayers.push_back(layerMap.size()); m_Chi2.push_back(track->fitQuality()->chiSquared()); m_DoF.push_back(track->fitQuality()->numberDoF()); @@ -1743,6 +1918,24 @@ NtupleDumperAlg::clearTree() const m_calo_total_raw_E_EM_fudged=0; m_calo_total_E_EM_fudged=0; + m_calolo_total_nMIP=0; + m_calolo_total_E_dep=0; + m_calolo_total_fit_E_EM=0; + m_calolo_total_raw_E_EM=0; + m_calolo_total_E_EM=0; + + m_calohi_total_nMIP=0; + m_calohi_total_E_dep=0; + m_calohi_total_fit_E_EM=0; + m_calohi_total_raw_E_EM=0; + m_calohi_total_E_EM=0; + + m_calonu_total_nMIP=0; + m_calonu_total_E_dep=0; + m_calonu_total_fit_E_EM=0; + m_calonu_total_raw_E_EM=0; + m_calonu_total_E_EM=0; + m_preshower_total_nMIP=0; m_preshower_total_E_dep=0; diff --git a/PhysicsAnalysis/NtupleDumper/src/NtupleDumperAlg.h b/PhysicsAnalysis/NtupleDumper/src/NtupleDumperAlg.h index ef4c227c2661a1c1faa115d19b6bb9d2d59f09c8..82601707399b0b0cc0c3e304bcbfb513e3d7cf9e 100644 --- a/PhysicsAnalysis/NtupleDumper/src/NtupleDumperAlg.h +++ b/PhysicsAnalysis/NtupleDumper/src/NtupleDumperAlg.h @@ -25,6 +25,7 @@ #include "FaserActsVertexing/IVertexingTool.h" #include "GeneratorObjects/McEventCollection.h" #include <boost/dynamic_bitset.hpp> +#include "ScintIdentifier/VetoID.h" #include "WaveformConditionsTools/IWaveformCableMappingTool.h" @@ -36,11 +37,7 @@ using HitSet = boost::dynamic_bitset<>; class TTree; class TH1; class FaserSCT_ID; -class VetoNuID; -class VetoID; -class TriggerID; -class PreshowerID; -class EcalID; + namespace TrackerDD { class SCT_DetectorManager; @@ -58,6 +55,7 @@ public: private: mutable bool m_first; + const VetoID* m_vetoID{nullptr}; bool waveformHitOK(const xAOD::WaveformHit* hit) const; void clearTree() const; @@ -65,10 +63,11 @@ private: void addBranch(const std::string &name,float* var) const; void addBranch(const std::string &name,unsigned int* var) const; void defineWaveBranches() const; - void addWaveBranches(const std::string &name, int nchannels, int first) const; void addWaveBranches(const std::string &name, std::list<int> channel_list) const; void FillWaveBranches(const xAOD::WaveformHitContainer &wave, bool isMC) const; - void addCalibratedBranches(const std::string &name, int nchannels, int first); + void addCalibratedBranches(const std::string &name, std::list<int> channel_list) const; + void addCaloSumBranches(const std::string &name) const ; + double radius(const Acts::Vector3 &position) const; // Return map with string as key and list<int> as value @@ -93,6 +92,8 @@ private: SG::ReadHandleKey<xAOD::WaveformHitContainer> m_vetoContainer { this, "VetoContainer", "VetoWaveformHits", "Veto hit container name" }; SG::ReadHandleKey<xAOD::WaveformHitContainer> m_triggerContainer { this, "TriggerContainer", "TriggerWaveformHits", "Trigger hit container name" }; SG::ReadHandleKey<xAOD::WaveformHitContainer> m_preshowerContainer { this, "PreshowerContainer", "PreshowerWaveformHits", "Preshower hit container name" }; + SG::ReadHandleKey<xAOD::WaveformHitContainer> m_muonContainer { this, "MuonContainer", "MuonWaveformHits", "Muon hit container name" }; + SG::ReadHandleKey<xAOD::WaveformHitContainer> m_ecalContainer { this, "EcalContainer", "CaloWaveformHits", "Ecal hit container name" }; SG::ReadHandleKey<xAOD::WaveformHitContainer> m_ecal2Container { this, "Ecal2Container", "Calo2WaveformHits", "Ecal hit container name" }; SG::ReadHandleKey<xAOD::WaveformHitContainer> m_caloNuContainer { this, "CaloNuContainer", "CaloNuWaveformHits", "CaloNu hit container name" }; @@ -157,6 +158,23 @@ private: double m_baseEventCrossSection {1.0}; const double kfemtoBarnsPerMilliBarn {1.0e12}; + // Flag for dual-gain calorimeter configuration + mutable bool m_dual_gain {false}; + + // Helper lists to hold channel lists + mutable std::list<int> m_calo_channels; + mutable std::list<int> m_calolo_channels; + mutable std::list<int> m_calohi_channels; + mutable std::list<int> m_calonu_channels; + + + // Output statistics + mutable int m_eventsPassed = 0; + mutable int m_eventsFailedGRL = 0; + mutable int m_two_tracks = 0; + mutable int m_verticies = 0; + + // Output tree mutable TTree* m_tree; //mutable unsigned int n_wave_chan; // Actual number of waveform channels @@ -213,19 +231,28 @@ private: mutable float m_calo_total_fit_E_EM_fudged; mutable float m_calo_total_raw_E_EM_fudged; mutable float m_calo_total_E_EM_fudged; + + mutable float m_calolo_total_nMIP; + mutable float m_calolo_total_E_dep; + mutable float m_calolo_total_fit_E_EM; + mutable float m_calolo_total_raw_E_EM; + mutable float m_calolo_total_E_EM; + + mutable float m_calohi_total_nMIP; + mutable float m_calohi_total_E_dep; + mutable float m_calohi_total_fit_E_EM; + mutable float m_calohi_total_raw_E_EM; + mutable float m_calohi_total_E_EM; + + mutable float m_calonu_total_nMIP; + mutable float m_calonu_total_E_dep; + mutable float m_calonu_total_fit_E_EM; + mutable float m_calonu_total_raw_E_EM; + mutable float m_calonu_total_E_EM; mutable float m_preshower_total_nMIP; mutable float m_preshower_total_E_dep; - mutable float m_Calo0_Edep; - mutable float m_Calo1_Edep; - mutable float m_Calo2_Edep; - mutable float m_Calo3_Edep; - - mutable float m_Calo_Total_Edep; - mutable float m_Preshower12_Edep; - mutable float m_Preshower13_Edep; - mutable float m_clock_phase; mutable unsigned int m_station0Clusters; @@ -416,12 +443,6 @@ private: mutable double m_crossSection; mutable std::vector<double> m_genWeights; - - mutable int m_eventsPassed = 0; - mutable int m_eventsFailedGRL = 0; - mutable int m_two_tracks = 0; - mutable int m_verticies = 0; - mutable double m_vertex_x; // components of reconstructed vertex in mm mutable double m_vertex_y; mutable double m_vertex_z; diff --git a/Scintillator/ScintDetDescr/ScintIdDictFiles/data/IdDictScintillator.xml b/Scintillator/ScintDetDescr/ScintIdDictFiles/data/IdDictScintillator.xml index 54552a212ae62ae33650c186ea6529c383524518..b223589bb147120c22245facb36683a3e23e8536 100644 --- a/Scintillator/ScintDetDescr/ScintIdDictFiles/data/IdDictScintillator.xml +++ b/Scintillator/ScintDetDescr/ScintIdDictFiles/data/IdDictScintillator.xml @@ -5,6 +5,7 @@ <label name="Trigger" value="2" /> <label name="Preshower" value="3" /> <label name="VetoNu" value="4" /> + <label name="Muon" value="5" /> </field> <region> @@ -25,7 +26,7 @@ <range field="part" value="Preshower" /> <range field="station" minvalue="0" maxvalue="0" /> <range field="plate" minvalue="0" maxvalue="1" /> - <range field="pmt" minvalue="0" maxvalue="0" /> + <range field="pmt" minvalue="0" maxvalue="1" /> </region> <region> @@ -35,4 +36,11 @@ <range field="pmt" minvalue="0" maxvalue="0" /> </region> + <region> + <range field="part" value="Muon" /> + <range field="station" minvalue="0" maxvalue="0" /> + <range field="plate" minvalue="0" maxvalue="1" /> + <range field="pmt" minvalue="0" maxvalue="0" /> + </region> + </IdDictionary> diff --git a/Scintillator/ScintDetDescr/ScintIdDictFiles/data/IdDictScintillator_2024.xml b/Scintillator/ScintDetDescr/ScintIdDictFiles/data/IdDictScintillator_2024.xml new file mode 100644 index 0000000000000000000000000000000000000000..54552a212ae62ae33650c186ea6529c383524518 --- /dev/null +++ b/Scintillator/ScintDetDescr/ScintIdDictFiles/data/IdDictScintillator_2024.xml @@ -0,0 +1,38 @@ +<IdDictionary name="Scintillator"> + + <field name="part" > + <label name="Veto" value="1" /> + <label name="Trigger" value="2" /> + <label name="Preshower" value="3" /> + <label name="VetoNu" value="4" /> + </field> + + <region> + <range field="part" value="Veto" /> + <range field="station" minvalue="0" maxvalue="1" /> + <range field="plate" minvalue="0" maxvalue="1" /> + <range field="pmt" minvalue="0" maxvalue="0" /> + </region> + + <region> + <range field="part" value="Trigger"/> + <range field="station" minvalue="0" maxvalue="0" /> + <range field="plate" minvalue="0" maxvalue="1" /> + <range field="pmt" minvalue="0" maxvalue="1" /> + </region> + + <region> + <range field="part" value="Preshower" /> + <range field="station" minvalue="0" maxvalue="0" /> + <range field="plate" minvalue="0" maxvalue="1" /> + <range field="pmt" minvalue="0" maxvalue="0" /> + </region> + + <region> + <range field="part" value="VetoNu" /> + <range field="station" minvalue="0" maxvalue="0" /> + <range field="plate" minvalue="0" maxvalue="1" /> + <range field="pmt" minvalue="0" maxvalue="0" /> + </region> + +</IdDictionary> diff --git a/Scintillator/ScintDetDescr/ScintIdDictFiles/data/IdDictScintillator_2025.xml b/Scintillator/ScintDetDescr/ScintIdDictFiles/data/IdDictScintillator_2025.xml new file mode 100644 index 0000000000000000000000000000000000000000..b223589bb147120c22245facb36683a3e23e8536 --- /dev/null +++ b/Scintillator/ScintDetDescr/ScintIdDictFiles/data/IdDictScintillator_2025.xml @@ -0,0 +1,46 @@ +<IdDictionary name="Scintillator"> + + <field name="part" > + <label name="Veto" value="1" /> + <label name="Trigger" value="2" /> + <label name="Preshower" value="3" /> + <label name="VetoNu" value="4" /> + <label name="Muon" value="5" /> + </field> + + <region> + <range field="part" value="Veto" /> + <range field="station" minvalue="0" maxvalue="1" /> + <range field="plate" minvalue="0" maxvalue="1" /> + <range field="pmt" minvalue="0" maxvalue="0" /> + </region> + + <region> + <range field="part" value="Trigger"/> + <range field="station" minvalue="0" maxvalue="0" /> + <range field="plate" minvalue="0" maxvalue="1" /> + <range field="pmt" minvalue="0" maxvalue="1" /> + </region> + + <region> + <range field="part" value="Preshower" /> + <range field="station" minvalue="0" maxvalue="0" /> + <range field="plate" minvalue="0" maxvalue="1" /> + <range field="pmt" minvalue="0" maxvalue="1" /> + </region> + + <region> + <range field="part" value="VetoNu" /> + <range field="station" minvalue="0" maxvalue="0" /> + <range field="plate" minvalue="0" maxvalue="1" /> + <range field="pmt" minvalue="0" maxvalue="0" /> + </region> + + <region> + <range field="part" value="Muon" /> + <range field="station" minvalue="0" maxvalue="0" /> + <range field="plate" minvalue="0" maxvalue="1" /> + <range field="pmt" minvalue="0" maxvalue="0" /> + </region> + +</IdDictionary> diff --git a/Scintillator/ScintDetDescr/ScintIdDictFiles/data/IdDictScintillator_TB00.xml b/Scintillator/ScintDetDescr/ScintIdDictFiles/data/IdDictScintillator_TB00.xml index 71fd8298645674dae3bd0d54c411d099742a6416..cab75a236bab883e237b4b43371bd86ab1babf39 100644 --- a/Scintillator/ScintDetDescr/ScintIdDictFiles/data/IdDictScintillator_TB00.xml +++ b/Scintillator/ScintDetDescr/ScintIdDictFiles/data/IdDictScintillator_TB00.xml @@ -5,6 +5,7 @@ <label name="Trigger" value="2" /> <label name="Preshower" value="3" /> <label name="VetoNu" value="4" /> + <label name="Muon" value="5" /> </field> <region> <range field="part" value="Veto" /> @@ -30,4 +31,10 @@ <range field="plate" minvalue="0" maxvalue="1" /> <range field="pmt" minvalue="0" maxvalue="0" /> </region> + <region> + <range field="part" value="Muon" /> + <range field="station" minvalue="0" maxvalue="0" /> + <range field="plate" minvalue="0" maxvalue="1" /> + <range field="pmt" minvalue="0" maxvalue="0" /> + </region> </IdDictionary> diff --git a/Scintillator/ScintDetDescr/ScintIdentifier/CMakeLists.txt b/Scintillator/ScintDetDescr/ScintIdentifier/CMakeLists.txt index 5874ae0de68035f16d71d47887a95cdfb8f857a6..7254bb74245059c09a09a09a27ac97f778fc18d8 100644 --- a/Scintillator/ScintDetDescr/ScintIdentifier/CMakeLists.txt +++ b/Scintillator/ScintDetDescr/ScintIdentifier/CMakeLists.txt @@ -14,6 +14,7 @@ atlas_add_library( ScintIdentifier src/VetoNuID.cxx src/TriggerID.cxx src/PreshowerID.cxx + src/MuonID.cxx # src/ScintillatorID.cxx PUBLIC_HEADERS ScintIdentifier PRIVATE_INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} diff --git a/Scintillator/ScintDetDescr/ScintIdentifier/ScintIdentifier/MuonID.h b/Scintillator/ScintDetDescr/ScintIdentifier/ScintIdentifier/MuonID.h new file mode 100644 index 0000000000000000000000000000000000000000..6f98f5f7b6ad9c9b3164ada087e4167612045b73 --- /dev/null +++ b/Scintillator/ScintDetDescr/ScintIdentifier/ScintIdentifier/MuonID.h @@ -0,0 +1,541 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef SCINTIDENTIFIER_MUONID_H +#define SCINTIDENTIFIER_MUONID_H +/** + * @file MuonID.h + * + * @brief This is an Identifier helper class for the Muon + * subdetector. This class is a factory for creating compact + * Identifier objects and IdentifierHash or hash ids. And it also + * allows decoding of these ids. + * + */ + +//<<<<<< INCLUDES >>>>>> + +#include "FaserDetDescr/FaserDetectorID.h" +#include "Identifier/Identifier.h" +#include "Identifier/IdentifierHash.h" +#include "Identifier/Range.h" +#include "Identifier/IdHelper.h" +#include "IdDict/IdDictFieldImplementation.h" +#include "AthenaKernel/CLASS_DEF.h" + +#include <string> +#include <assert.h> +#include <algorithm> + +//<<<<<< PUBLIC DEFINES >>>>>> +//<<<<<< PUBLIC CONSTANTS >>>>>> +//<<<<<< PUBLIC TYPES >>>>>> + +class IdDictDictionary; + +//<<<<<< PUBLIC VARIABLES >>>>>> +//<<<<<< PUBLIC FUNCTIONS >>>>>> +//<<<<<< CLASS DECLARATIONS >>>>>> + +/** + ** @class MuonID + ** + ** @brief This is an Identifier helper class for the Muon + ** subdetector. This class is a factory for creating compact + ** Identifier objects and IdentifierHash or hash ids. And it also + ** allows decoding of these ids. + ** + ** Definition and the range of values for the levels of the + ** identifier are: + ** + ** @verbatim + ** element range meaning + ** ------- ----- ------- + ** + ** station 0 longitudinal location + ** plate 0 to 1 two plates per station + ** pmt 0 single pmt per plate + ** + ** @endverbatim + ** + */ +class MuonID : public FaserDetectorID +{ +public: + + /// @name public typedefs + //@{ + typedef Identifier::size_type size_type; + typedef std::vector<Identifier>::const_iterator const_id_iterator; + typedef MultiRange::const_identifier_factory const_expanded_id_iterator; + //@} + + /// @name strutors + //@{ + MuonID(void); + virtual ~MuonID(void) = default; + //@} + + /// @name Creators for plate ids and pmt ids + //@{ + /// For a single station + Identifier station_id ( int station ) const; + Identifier station_id ( int station, + bool checks) const; + + /// For a station from a plate id + Identifier station_id ( const Identifier& plate_id ) const; + + /// For a single plate + Identifier plate_id ( int station, + int plate ) const; + Identifier plate_id ( int station, + int plate, + bool checks) const; + + /// For a single plate from a pmt id + Identifier plate_id ( const Identifier& pmt_id ) const; + + /// From hash - optimized + Identifier plate_id ( IdentifierHash plate_hash ) const; + + /// For an individual pmt + Identifier pmt_id ( int station, + int plate, + int pmt ) const; + + Identifier pmt_id ( int station, + int plate, + int pmt, + bool check ) const; + + Identifier pmt_id ( const Identifier& plate_id, + int pmt ) const; + + //@} + + + /// @name Hash table maximum sizes + //@{ + size_type plate_hash_max (void) const; + size_type pmt_hash_max (void) const; + //@} + + /// @name Access to all ids + //@{ + /// Iterators over full set of ids. Plate iterator is sorted + const_id_iterator plate_begin (void) const; + const_id_iterator plate_end (void) const; + /// For pmt ids, only expanded id iterators are available. Use + /// following "pmt_id" method to obtain a compact identifier + const_expanded_id_iterator pmt_begin (void) const; + const_expanded_id_iterator pmt_end (void) const; + //@} + + + /// @name Optimized accessors - ASSUMES id IS a muon id, i.e. NOT other + //@{ + /// wafer hash from id - optimized + IdentifierHash plate_hash (Identifier plate_id) const; + + /// Values of different levels (failure returns 0) + int station (const Identifier& id) const; + int plate (const Identifier& id) const; + int pmt (const Identifier& id) const; + + /// Max/Min values for each field (-999 == failure) + int station_max (const Identifier& id) const; + int plate_max (const Identifier& id) const; + int pmt_max (const Identifier& id) const; + //@} + + /// @name module navigation + //@{ + /// Previous plate in z + int get_prev_in_z(const IdentifierHash& id, IdentifierHash& prev) const; + /// Next plate in z + int get_next_in_z(const IdentifierHash& id, IdentifierHash& next) const; + // /// Previous wafer hash in phi (return == 0 for neighbor found) + // int get_prev_in_phi (const IdentifierHash& id, IdentifierHash& prev) const; + // /// Next wafer hash in phi (return == 0 for neighbor found) + // int get_next_in_phi (const IdentifierHash& id, IdentifierHash& next) const; + // /// Previous wafer hash in eta (return == 0 for neighbor found) + // int get_prev_in_eta (const IdentifierHash& id, IdentifierHash& prev) const; + // /// Next wafer hash in eta (return == 0 for neighbor found) + // int get_next_in_eta (const IdentifierHash& id, IdentifierHash& next) const; + // /// Wafer hash on other side + // int get_other_side (const IdentifierHash& id, IdentifierHash& other) const; + + // // To check for when phi wrap around may be needed, use + // bool is_phi_module_max(const Identifier& id) const; + // /// For the barrel + // bool is_eta_module_min(const Identifier& id) const; + // /// For the barrel + // bool is_eta_module_max(const Identifier& id) const; + //@} + + /// @name contexts to distinguish plate id from pixel id + //@{ + IdContext plate_context (void) const; + IdContext pmt_context (void) const; + //@} + + /// @name methods from abstract interface - slower than opt version + //@{ + /// Create compact id from hash id (return == 0 for OK) + virtual int get_id (const IdentifierHash& hash_id, + Identifier& id, + const IdContext* context = 0) const; + + /// Create hash id from compact id (return == 0 for OK) + virtual int get_hash (const Identifier& id, + IdentifierHash& hash_id, + const IdContext* context = 0) const; + //@} + + /// Return the lowest bit position used in the channel id + int base_bit (void) const; + + /// Calculate a channel offset between the two identifiers. + Identifier::diff_type calc_offset(const Identifier& base, + const Identifier& target) const; + + /// Create an identifier with a given base and channel offset + Identifier pmt_id_offset(const Identifier& base, + Identifier::diff_type offset) const; + + /// @name interaction with id dictionary + //@{ + /// Create strip Identifier from expanded id, which is returned by the + /// id_iterators + Identifier pmt_id (const ExpandedIdentifier& pmt_id) const; + + /// Create expanded id from compact id (return == 0 for OK) + void get_expanded_id (const Identifier& id, + ExpandedIdentifier& exp_id, + const IdContext* context = 0) const; + + /// Initialization from the identifier dictionary + virtual int initialize_from_dictionary(const IdDictMgr& dict_mgr); + + /// Tests of packing + void test_plate_packing (void) const; + //@} + +private: + + enum {NOT_VALID_HASH = 64000}; + + typedef std::vector<Identifier> id_vec; + typedef id_vec::const_iterator id_vec_it; + typedef std::vector<unsigned short> hash_vec; + typedef hash_vec::const_iterator hash_vec_it; + + void plate_id_checks ( int station, + int plate ) const; + + void pmt_id_checks ( int station, + int plate, + int pmt ) const; + + + int initLevelsFromDict(void); + + int init_hashes(void); + + int init_neighbors(void); + + // Temporary method for adapting an identifier for the MultiRange + // check - MR is missing the InnerDetector level + // Identifier idForCheck (const Identifier& id) const; + + size_type m_muon_region_index; + size_type m_SCINT_INDEX; + size_type m_MUON_INDEX; + size_type m_STATION_INDEX; + size_type m_PLATE_INDEX; + size_type m_PMT_INDEX; + + const IdDictDictionary* m_dict; + MultiRange m_full_plate_range; + MultiRange m_full_pmt_range; + size_type m_plate_hash_max; + size_type m_pmt_hash_max; + // Range::field m_barrel_field; + id_vec m_plate_vec; + hash_vec m_prev_z_plate_vec; + hash_vec m_next_z_plate_vec; + // hash_vec m_prev_phi_wafer_vec; + // hash_vec m_next_phi_wafer_vec; + // hash_vec m_prev_eta_wafer_vec; + // hash_vec m_next_eta_wafer_vec; + // bool m_hasRows ; + + IdDictFieldImplementation m_scint_impl ; + IdDictFieldImplementation m_muon_impl ; + IdDictFieldImplementation m_station_impl ; + IdDictFieldImplementation m_plate_impl ; + IdDictFieldImplementation m_pmt_impl ; +}; + + +//<<<<<< INLINE PUBLIC FUNCTIONS >>>>>> + +///////////////////////////////////////////////////////////////////////////// +//<<<<<< INLINE MEMBER FUNCTIONS >>>>>> +///////////////////////////////////////////////////////////////////////////// + +//using the macros below we can assign an identifier (and a version) +//This is required and checked at compile time when you try to record/retrieve +CLASS_DEF(MuonID, 143274416, 1) + +//---------------------------------------------------------------------------- +inline Identifier +MuonID::station_id ( int station, + bool checks) const +{ + + // Build identifier + Identifier result((Identifier::value_type)0); + + // Pack fields independently + m_scint_impl.pack (scint_field_value(), result); + m_muon_impl.pack (muon_field_value(), result); + m_station_impl.pack (station, result); + // Do checks + if(checks) + { + plate_id_checks ( station, 0 ); + } + + return result; +} + +inline Identifier +MuonID::station_id ( int station ) const +{ + return station_id (station, do_checks()); +} + +//---------------------------------------------------------------------------- +inline Identifier +MuonID::station_id ( const Identifier& plate_id ) const +{ + Identifier result(plate_id); + // Reset the plate and pmt fields + m_plate_impl.reset(result); + m_pmt_impl.reset(result); + return (result); +} + +//---------------------------------------------------------------------------- +inline Identifier +MuonID::plate_id ( int station, + int plate, + bool checks) const +{ + // Build identifier + Identifier result((Identifier::value_type)0); + + // Pack fields independently + m_scint_impl.pack (scint_field_value(), result); + m_muon_impl.pack (muon_field_value(), result); + m_station_impl.pack (station, result); + m_plate_impl.pack (plate, result); + + // Do checks + if(checks) + { + plate_id_checks ( station, plate ); + } + return result; +} + +inline Identifier +MuonID::plate_id ( int station, + int plate ) const +{ + return plate_id (station, plate, do_checks()); +} + +//---------------------------------------------------------------------------- +inline Identifier +MuonID::plate_id ( const Identifier& pmt_id ) const +{ + Identifier result(pmt_id); + // reset the pmt field + m_pmt_impl.reset(result); + return (result); +} + +//---------------------------------------------------------------------------- +inline Identifier MuonID::plate_id ( IdentifierHash plate_hash ) const +{ + return (m_plate_vec[plate_hash]); +} + +//---------------------------------------------------------------------------- +inline IdentifierHash MuonID::plate_hash (Identifier plate_id) const +{ + // MsgStream log(m_msgSvc, "MuonID"); + // log << MSG::VERBOSE << "m_plate_vec size: " << m_plate_vec.size() << endmsg; + // log << MSG::VERBOSE << "input id = " << plate_id << endmsg; + // for (size_t i = 0; i < m_plate_vec.size(); i++) + // { + // log << MSG::VERBOSE << "Hash = " << i << " : ID = " << m_plate_vec[i] << endmsg; + // } + id_vec_it it = std::lower_bound(m_plate_vec.begin(), + m_plate_vec.end(), + plate_id); + // Require that plate_id matches the one in vector + if (it != m_plate_vec.end() && plate_id == (*it)) { + return (it - m_plate_vec.begin()); + } + IdentifierHash result; + return (result); // return hash in invalid state +} + +//---------------------------------------------------------------------------- +inline Identifier +MuonID::pmt_id ( int station, + int plate, + int pmt, + bool checks) const +{ + // Build identifier + Identifier result((Identifier::value_type)0); + + // Pack fields independently + m_scint_impl.pack (scint_field_value(), result); + m_muon_impl.pack (muon_field_value(),result); + m_station_impl.pack (station, result); + m_plate_impl.pack (plate, result); + m_pmt_impl.pack (pmt, result); + + // Do checks + if(checks) { + pmt_id_checks ( station, plate, pmt ); + } + return result; +} + +inline Identifier +MuonID::pmt_id ( int station, + int plate, + int pmt ) const +{ + return pmt_id (station, plate, pmt, do_checks()); +} + +//---------------------------------------------------------------------------- +inline Identifier +MuonID::pmt_id (const ExpandedIdentifier& id) const +{ + // Build identifier + Identifier result((Identifier::value_type)0); + + // Pack fields independently + m_scint_impl.pack (scint_field_value(), result); + m_muon_impl.pack (muon_field_value(), result); + m_station_impl.pack (id[m_STATION_INDEX], result); + m_plate_impl.pack (id[m_PLATE_INDEX], result); + m_pmt_impl.pack (id[m_PMT_INDEX], result); + + // Do checks + if(m_do_checks) + { + pmt_id_checks ( id[m_STATION_INDEX], + id[m_PLATE_INDEX], + id[m_PMT_INDEX]); + } + return result; +} + +//---------------------------------------------------------------------------- +inline Identifier +MuonID::pmt_id ( const Identifier& plate_id, int pmt ) const +{ + // Build identifier + Identifier result(plate_id); + + // Reset strip and then add in value + m_pmt_impl.reset (result); + m_pmt_impl.pack (pmt, result); + + if(m_do_checks) + { + pmt_id_checks ( station(result), + plate(result), + pmt ); + } + return result; +} + +//---------------------------------------------------------------------------- +inline Identifier::diff_type +MuonID::calc_offset(const Identifier& base, const Identifier& target) const +{ + Identifier::diff_type tval = static_cast<Identifier::diff_type>(target.get_compact() >> base_bit()); + Identifier::diff_type bval = static_cast<Identifier::diff_type>(base.get_compact() >> base_bit()); + return (tval - bval); +} + +//---------------------------------------------------------------------------- +inline Identifier +MuonID::pmt_id_offset(const Identifier& base, + Identifier::diff_type offset) const +{ + Identifier::value_type bval = base.get_compact() >> base_bit(); + return Identifier((bval + offset) << base_bit()); +} + +//---------------------------------------------------------------------------- +inline int +MuonID::base_bit ( void ) const +{ + int base = static_cast<int>(m_pmt_impl.shift()); // lowest field base + return (base > 32) ? 32 : base; + // max base is 32 so we can still read old strip id's and differences + // from non-SLHC releases. +} + +//---------------------------------------------------------------------------- +inline IdContext +MuonID::plate_context (void) const +{ + ExpandedIdentifier id; + return (IdContext(id, 0, m_PLATE_INDEX)); +} + +//---------------------------------------------------------------------------- +inline IdContext +MuonID::pmt_context (void) const +{ + ExpandedIdentifier id; + return (IdContext(id, 0, m_PMT_INDEX)); +} + +//---------------------------------------------------------------------------- +inline int +MuonID::station (const Identifier& id) const +{ + return (m_station_impl.unpack(id)); +} + +//---------------------------------------------------------------------------- +inline int +MuonID::plate (const Identifier& id) const +{ + return (m_plate_impl.unpack(id)); +} + +//---------------------------------------------------------------------------- +inline int +MuonID::pmt (const Identifier& id) const +{ + return (m_pmt_impl.unpack(id)); +} + + +#endif // SCINTIDENTIFIER_MUONID_H diff --git a/Scintillator/ScintDetDescr/ScintIdentifier/ScintIdentifier/ScintIdentifierDict.h b/Scintillator/ScintDetDescr/ScintIdentifier/ScintIdentifier/ScintIdentifierDict.h index 0968f0b4136d48216bcea7305e4933dac7337e2d..0d7b3a899cb7194622580e6919dba542805e5f5c 100644 --- a/Scintillator/ScintDetDescr/ScintIdentifier/ScintIdentifier/ScintIdentifierDict.h +++ b/Scintillator/ScintDetDescr/ScintIdentifier/ScintIdentifier/ScintIdentifierDict.h @@ -17,5 +17,6 @@ #include "ScintIdentifier/TriggerID.h" #include "ScintIdentifier/VetoID.h" #include "ScintIdentifier/VetoNuID.h" +#include "ScintIdentifier/MuonID.h" #endif // SCINTIDENTIFIER_SCINTIDENTIFIERDICT_H diff --git a/Scintillator/ScintDetDescr/ScintIdentifier/ScintIdentifier/selection.xml b/Scintillator/ScintDetDescr/ScintIdentifier/ScintIdentifier/selection.xml index bebeff9ec46d1ef9554a176ba64038033469d21b..1bb2349acc40fc37f7a1d6d284a9b2de23b735e3 100644 --- a/Scintillator/ScintDetDescr/ScintIdentifier/ScintIdentifier/selection.xml +++ b/Scintillator/ScintDetDescr/ScintIdentifier/ScintIdentifier/selection.xml @@ -6,4 +6,5 @@ <class name="VetoNuID" /> <class name="TriggerID" /> <class name="PreshowerID" /> + <class name="MuonID" /> </lcgdict> diff --git a/Scintillator/ScintDetDescr/ScintIdentifier/src/MuonID.cxx b/Scintillator/ScintDetDescr/ScintIdentifier/src/MuonID.cxx new file mode 100644 index 0000000000000000000000000000000000000000..c219b7d5504faa3a420363c31f9ab791259f423a --- /dev/null +++ b/Scintillator/ScintDetDescr/ScintIdentifier/src/MuonID.cxx @@ -0,0 +1,1030 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +/*************************************************************************** + Scintillator identifier package + ------------------------------------------- +***************************************************************************/ + +//<<<<<< INCLUDES >>>>>> +#include "GaudiKernel/MsgStream.h" + +#include "ScintIdentifier/MuonID.h" +#include "Identifier/IdentifierHash.h" +#include "IdDict/IdDictDefs.h" +#include <set> +#include <algorithm> +#include <iostream> + +//<<<<<< PRIVATE DEFINES >>>>>> +//<<<<<< PRIVATE CONSTANTS >>>>>> +//<<<<<< PRIVATE TYPES >>>>>> +//<<<<<< PRIVATE VARIABLE DEFINITIONS >>>>>> +//<<<<<< PUBLIC VARIABLE DEFINITIONS >>>>>> +//<<<<<< CLASS STRUCTURE INITIALIZATION >>>>>> +//<<<<<< PRIVATE FUNCTION DEFINITIONS >>>>>> +//<<<<<< PUBLIC FUNCTION DEFINITIONS >>>>>> +//<<<<<< MEMBER FUNCTION DEFINITIONS >>>>>> + + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + + +MuonID::MuonID(void) + : + m_muon_region_index(0), + m_SCINT_INDEX(0), + m_MUON_INDEX(1), + m_STATION_INDEX(2), + m_PLATE_INDEX(3), + m_PMT_INDEX(4), + m_dict(0), + m_plate_hash_max(0), + m_pmt_hash_max(0) +{ +} + +void +MuonID::plate_id_checks ( int station, + int plate ) const +{ + + // Check that id is within allowed range + + // Fill expanded id + ExpandedIdentifier id; + id << scint_field_value() << muon_field_value() + << station << plate; + + if (!m_full_plate_range.match(id)) { // module range check is sufficient + MsgStream log(m_msgSvc, "MuonID"); + log << MSG::ERROR << " MuonID::plate_id result is NOT ok. ID, range " + << (std::string)id << " " << (std::string)m_full_plate_range << endmsg; + } +} + +void +MuonID::pmt_id_checks ( int station, + int plate, + int pmt) const +{ + + // Check that id is within allowed range + + // Fill expanded id + ExpandedIdentifier id; + id << scint_field_value() << muon_field_value() + << station << plate << pmt; + + if (!m_full_pmt_range.match(id)) { + MsgStream log(m_msgSvc, "MuonID"); + log << MSG::ERROR << " MuonID::pmt_id result is NOT ok. ID, range " + << (std::string)id << " " << (std::string)m_full_pmt_range << std::endl; + } +} + +int +MuonID::station_max(const Identifier& id) const +{ + // get max from dictionary + ExpandedIdentifier expId; + IdContext plate_context1 = plate_context(); + get_expanded_id(id, expId, &plate_context1); + for (unsigned int i = 0; i < m_full_plate_range.size(); ++i) { + const Range& range = m_full_plate_range[i]; + if (range.match(expId)) { + const Range::field& station_field = range[m_STATION_INDEX]; + if (station_field.has_maximum()) { + return (station_field.get_maximum()); + } + } + } + return (-999); // default +} + +int +MuonID::pmt_max (const Identifier& id) const +{ + ExpandedIdentifier expId; + IdContext station_context(expId, 0, m_STATION_INDEX); + get_expanded_id(id, expId, &station_context); + int result = -999; + for (unsigned int i = 0; i < m_full_pmt_range.size(); ++i) { + const Range& range = m_full_pmt_range[i]; + if (range.match(expId)) { + const Range::field& pmt_field = range[m_PMT_INDEX]; + if (pmt_field.has_maximum()) { + int pmt = pmt_field.get_maximum(); + if (result < pmt) result = pmt; + } + } + } + return (result); +} + +int +MuonID::plate_max(const Identifier& id) const +{ + // get max from dictionary + ExpandedIdentifier expId; + IdContext plate_context1 = plate_context(); + get_expanded_id(id, expId, &plate_context1); + for (unsigned int i = 0; i < m_full_plate_range.size(); ++i) { + const Range& range = m_full_plate_range[i]; + if (range.match(expId)) { + const Range::field& plate_field = range[m_PLATE_INDEX]; + if (plate_field.has_maximum()) { + return (plate_field.get_maximum()); + } + } + } + return -1; +} + +int +MuonID::initialize_from_dictionary(const IdDictMgr& dict_mgr) +{ + MsgStream log(m_msgSvc, "MuonID"); + log << MSG::INFO << "Initialize from dictionary" << endmsg; + + // Check whether this helper should be reinitialized + if (!reinitialize(dict_mgr)) { + log << MSG::INFO << "Request to reinitialize not satisfied - tags have not changed" << endmsg; + return (0); + } + else { + if (m_msgSvc) { + log << MSG::DEBUG << "(Re)initialize" << endmsg; + } + else { + std::cout << " DEBUG (Re)initialize" << std::endl; + } + } + + // init base object + if(FaserDetectorID::initialize_from_dictionary(dict_mgr)) return (1); + + // Register version of InnerDetector dictionary + if (register_dict_tag(dict_mgr, "Scintillator")) return(1); + + m_dict = dict_mgr.find_dictionary ("Scintillator"); + if(!m_dict) { + log << MSG::ERROR << " MuonID::initialize_from_dict - cannot access Scintillator dictionary " << endmsg; + return 1; + } + + // Initialize the field indices + if(initLevelsFromDict()) return (1); + + // + // Build multirange for the valid set of identifiers + // + + + // Find value for the field Scintillator + const IdDictDictionary* faserDict = dict_mgr.find_dictionary ("FASER"); + int scintField = -1; + if (faserDict->get_label_value("subdet", "Scintillator", scintField)) { + log << MSG::ERROR << "Could not get value for label 'Scintillator' of field 'subdet' in dictionary " + << faserDict->m_name + << endmsg; + return (1); + } + + // Find value for the field Muon + int muonField = -1; + if (m_dict->get_label_value("part", "Muon", muonField)) { + log << MSG::ERROR << "Could not get value for label 'Muon' of field 'part' in dictionary " + << m_dict->m_name + << endmsg; + return (1); + } + if (m_msgSvc) { + log << MSG::DEBUG << " MuonID::initialize_from_dict " + << "Found field values: Muon " + << muonField + << std::endl; + } + else { + std::cout << " DEBUG MuonID::initialize_from_dict " + << "Found field values: Muon " + << muonField + << std::endl; + } + + // Set up id for region and range prefix + ExpandedIdentifier region_id; + region_id.add(scintField); + region_id.add(muonField); + Range prefix; + m_full_plate_range = m_dict->build_multirange(region_id, prefix, "plate"); + m_full_pmt_range = m_dict->build_multirange(region_id, prefix); + + // Setup the hash tables + if(init_hashes()) return (1); + + // Setup hash tables for finding neighbors + if(init_neighbors()) return (1); + + if (m_msgSvc) { + log << MSG::INFO << " MuonID::initialize_from_dict " << endmsg; + log << MSG::DEBUG + << "Plate range -> " << (std::string)m_full_plate_range + << endmsg; + log << MSG::DEBUG + << "Pmt range -> " << (std::string)m_full_pmt_range + << endmsg; + } + else { + std::cout << " INFO MuonID::initialize_from_dict " << std::endl; + std::cout << " DEBUG Plate range -> " << (std::string)m_full_plate_range + << std::endl; + std::cout << " DEBUG Pmt range -> " << (std::string)m_full_pmt_range + << std::endl; + } + + return 0; +} + +int +MuonID::init_hashes(void) +{ + + // + // create a vector(s) to retrieve the hashes for compact ids. For + // the moment, we implement a hash for plates but NOT for pmts + // + MsgStream log(m_msgSvc, "MuonID"); + // plate hash + m_plate_hash_max = m_full_plate_range.cardinality(); + m_plate_vec.resize(m_plate_hash_max); + unsigned int nids = 0; + std::set<Identifier> ids; + for (unsigned int i = 0; i < m_full_plate_range.size(); ++i) { + const Range& range = m_full_plate_range[i]; + Range::const_identifier_factory first = range.factory_begin(); + Range::const_identifier_factory last = range.factory_end(); + for (; first != last; ++first) { + const ExpandedIdentifier& exp_id = (*first); + Identifier id = plate_id(exp_id[m_STATION_INDEX], + exp_id[m_PLATE_INDEX]); + if(!(ids.insert(id)).second) { + log << MSG::ERROR << " MuonID::init_hashes " + << " Error: duplicated id for plate id. nid " << nids + << " compact id " << id.getString() + << " id " << (std::string)exp_id << endmsg; + return (1); + } + nids++; + } + } + if(ids.size() != m_plate_hash_max) { + log << MSG::ERROR << " MuonID::init_hashes " + << " Error: set size NOT EQUAL to hash max. size " << ids.size() + << " hash max " << m_plate_hash_max + << endmsg; + return (1); + } + + nids = 0; + std::set<Identifier>::const_iterator first = ids.begin(); + std::set<Identifier>::const_iterator last = ids.end(); + for (; first != last && nids < m_plate_vec.size(); ++first) { + m_plate_vec[nids] = (*first); + nids++; + } + + // pmt hash - we do not keep a vec for the pmts + m_pmt_hash_max = m_full_pmt_range.cardinality(); + + return (0); +} + + int + MuonID::get_prev_in_z(const IdentifierHash& id, IdentifierHash& prev) const + { + unsigned short index = id; + if (index < m_prev_z_plate_vec.size()) + { + if (m_prev_z_plate_vec[index] == NOT_VALID_HASH) return (1); + prev = m_prev_z_plate_vec[index]; + return (0); + } + return (1); + } + + int + MuonID::get_next_in_z(const IdentifierHash& id, IdentifierHash& next) const + { + unsigned short index = id; + if (index < m_next_z_plate_vec.size()) + { + if (m_next_z_plate_vec[index] == NOT_VALID_HASH) return (1); + next = m_next_z_plate_vec[index]; + return (0); + } + return (1); + } + +// int +// MuonID::get_prev_in_phi(const IdentifierHash& id, IdentifierHash& prev) const +// { +// unsigned short index = id; +// if (index < m_prev_phi_wafer_vec.size()) { +// if (m_prev_phi_wafer_vec[index] == NOT_VALID_HASH) return (1); +// prev = m_prev_phi_wafer_vec[index]; +// return (0); +// } +// return (1); +// } + +// int +// MuonID::get_next_in_phi(const IdentifierHash& id, IdentifierHash& next) const +// { +// unsigned short index = id; +// if (index < m_next_phi_wafer_vec.size()) { +// if (m_next_phi_wafer_vec[index] == NOT_VALID_HASH) return (1); +// next = m_next_phi_wafer_vec[index]; +// return (0); +// } +// return (1); +// } + +// int +// MuonID::get_prev_in_eta(const IdentifierHash& id, IdentifierHash& prev) const +// { +// unsigned short index = id; +// if (index < m_prev_eta_wafer_vec.size()) { +// if (m_prev_eta_wafer_vec[index] == NOT_VALID_HASH) return (1); +// prev = m_prev_eta_wafer_vec[index]; +// return (0); +// } +// return (1); +// } + +// int +// MuonID::get_next_in_eta(const IdentifierHash& id, IdentifierHash& next) const +// { +// unsigned short index = id; +// if (index < m_next_eta_wafer_vec.size()) { +// if (m_next_eta_wafer_vec[index] == NOT_VALID_HASH) return (1); +// next = m_next_eta_wafer_vec[index]; +// return (0); +// } +// return (1); +// } + +// int +// MuonID::get_other_side (const IdentifierHash& hashId, IdentifierHash& other) const +// { +// if (m_dict) { +// // get max from dictionary +// Identifier id; +// IdContext wafer_context1 = wafer_context(); +// if(!get_id(hashId, id, &wafer_context1)) { +// other = side(id) ? hashId - 1 : hashId + 1; +// return (0); +// } +// } +// return (1); +// } + +int +MuonID::init_neighbors(void) +{ + // + // create a vector(s) to retrieve the hashes for compact ids for + // plate neighbors. + // + MsgStream log(m_msgSvc, "MuonID"); + + m_prev_z_plate_vec.resize(m_plate_hash_max, NOT_VALID_HASH); + m_next_z_plate_vec.resize(m_plate_hash_max, NOT_VALID_HASH); + for (unsigned int i = 0; i < m_full_plate_range.size(); i++) + { + const Range& range = m_full_plate_range[i]; + const Range::field& station_field = range[m_STATION_INDEX]; + const Range::field& plate_field = range[m_PLATE_INDEX]; + Range::const_identifier_factory first = range.factory_begin(); + Range::const_identifier_factory last = range.factory_end(); + for (; first != last; ++first) + { + const ExpandedIdentifier& exp_id = (*first); + ExpandedIdentifier::element_type previous_plate; + ExpandedIdentifier::element_type next_plate; + ExpandedIdentifier::element_type previous_station; + ExpandedIdentifier::element_type next_station; + bool pplate = plate_field.get_previous(exp_id[m_PLATE_INDEX], previous_plate); + bool nplate = plate_field.get_next (exp_id[m_PLATE_INDEX], next_plate); + bool pstation = station_field.get_previous(exp_id[m_STATION_INDEX], previous_station); + bool nstation = station_field.get_next (exp_id[m_STATION_INDEX], next_station); + + IdContext pcontext = plate_context(); + + IdentifierHash hash_id; + Identifier originalId = plate_id(exp_id[m_STATION_INDEX], + exp_id[m_PLATE_INDEX]); + + if (get_hash(originalId, hash_id, &pcontext)) + { + log << MSG::ERROR << " MuonID::init_neighbors - unable to get hash, exp/compact " + << show_to_string(originalId, &pcontext) + << " " << (std::string)m_full_plate_range << endmsg; + return (1); + } + + // index for the subsequent arrays + unsigned short index = hash_id; + assert (hash_id < m_prev_z_plate_vec.size()); + assert (hash_id < m_next_z_plate_vec.size()); + + if (pplate) { + // Get previous plate hash id + ExpandedIdentifier expId = exp_id; + expId[m_PLATE_INDEX] = previous_plate; + Identifier id = plate_id(expId[m_STATION_INDEX], + expId[m_PLATE_INDEX]); + + if (get_hash(id, hash_id, &pcontext)) { + log << MSG::ERROR << " MuonID::init_neighbors - unable to get previous plate hash, exp/compact " << id.getString() << " " + << endmsg; + return (1); + } + m_prev_z_plate_vec[index] = hash_id; + } + else if (pstation) + { + ExpandedIdentifier expId = exp_id; + expId[m_STATION_INDEX] = previous_station; + ExpandedIdentifier stationId; + stationId.add(expId[m_SCINT_INDEX]); + stationId.add(expId[m_MUON_INDEX]); + stationId.add(previous_station); + Range prefix; + MultiRange stationPlateRange = m_dict->build_multirange(stationId, prefix, "plate"); + const Range::field& upstream_plate_field = range[m_PLATE_INDEX]; + if (upstream_plate_field.has_maximum()) + { + expId[m_PLATE_INDEX] = upstream_plate_field.get_maximum(); + Identifier id = plate_id(expId[m_STATION_INDEX], + expId[m_PLATE_INDEX]); + if (get_hash(id, hash_id, &pcontext)) { + log << MSG::ERROR << " MuonID::init_neighbors - unable to get last plate hash from previous station, exp/compact " << id.getString() << " " + << endmsg; + return (1); + } + m_prev_z_plate_vec[index] = hash_id; + } + else + { + log << MSG::ERROR << "MuonID::init_neighbors - unable to get plate_max for previous station, exp/compact " << originalId.getString() << " " + << endmsg; + return (1); + } + } + + if (nplate) { + // Get next plate hash id + ExpandedIdentifier expId = exp_id; + expId[m_PLATE_INDEX] = next_plate; + Identifier id = plate_id(expId[m_STATION_INDEX], + expId[m_PLATE_INDEX]); + + if (get_hash(id, hash_id, &pcontext)) { + log << MSG::ERROR << " MuonID::init_neighbors - unable to get next plate hash, exp/compact " << id.getString() << " " + << endmsg; + return (1); + } + m_next_z_plate_vec[index] = hash_id; + } + else if (nstation) + { + ExpandedIdentifier expId = exp_id; + expId[m_STATION_INDEX] = next_station; + ExpandedIdentifier stationId; + stationId.add(expId[m_SCINT_INDEX]); + stationId.add(expId[m_MUON_INDEX]); + stationId.add(next_station); + Range prefix; + MultiRange stationPlateRange = m_dict->build_multirange(stationId, prefix, "plate"); + const Range::field& downstream_plate_field = range[m_PLATE_INDEX]; + if (downstream_plate_field.has_minimum()) + { + expId[m_PLATE_INDEX] = downstream_plate_field.get_minimum(); + Identifier id = plate_id(expId[m_STATION_INDEX], + expId[m_PLATE_INDEX]); + if (get_hash(id, hash_id, &pcontext)) { + log << MSG::ERROR << " MuonID::init_neighbors - unable to get previous plate hash from next station, exp/compact " << id.getString() << " " + << endmsg; + return (1); + } + m_next_z_plate_vec[index] = hash_id; + } + else + { + log << MSG::ERROR << "MuonID::init_neighbors - unable to get plate_min for next station, exp/compact " << originalId.getString() << " " + << endmsg; + return (1); + } + } + + } + } + + // m_prev_phi_wafer_vec.resize(m_wafer_hash_max, NOT_VALID_HASH); + // m_next_phi_wafer_vec.resize(m_wafer_hash_max, NOT_VALID_HASH); + // m_prev_eta_wafer_vec.resize(m_wafer_hash_max, NOT_VALID_HASH); + // m_next_eta_wafer_vec.resize(m_wafer_hash_max, NOT_VALID_HASH); + + // for (unsigned int i = 0; i < m_full_wafer_range.size(); ++i) { + // const Range& range = m_full_wafer_range[i]; + // const Range::field& phi_field = range[m_PHI_MODULE_INDEX]; + // const Range::field& eta_field = range[m_ETA_MODULE_INDEX]; + // Range::const_identifier_factory first = range.factory_begin(); + // Range::const_identifier_factory last = range.factory_end(); + // for (; first != last; ++first) { + // const ExpandedIdentifier& exp_id = (*first); + // ExpandedIdentifier::element_type previous_phi; + // ExpandedIdentifier::element_type next_phi; + // ExpandedIdentifier::element_type previous_eta; + // ExpandedIdentifier::element_type next_eta; + // bool pphi = phi_field.get_previous(exp_id[m_PHI_MODULE_INDEX], previous_phi); + // bool nphi = phi_field.get_next (exp_id[m_PHI_MODULE_INDEX], next_phi); + // bool peta = eta_field.get_previous(exp_id[m_ETA_MODULE_INDEX], previous_eta); + // bool neta = eta_field.get_next (exp_id[m_ETA_MODULE_INDEX], next_eta); + + // IdContext wcontext = wafer_context(); + + // // First get primary hash id + // IdentifierHash hash_id; + // Identifier id = wafer_id(exp_id[m_BARREL_EC_INDEX], + // exp_id[m_LAYER_DISK_INDEX], + // exp_id[m_PHI_MODULE_INDEX], + // exp_id[m_ETA_MODULE_INDEX], + // exp_id[m_SIDE_INDEX]); + // if (get_hash(id, hash_id, &wcontext)) { + // log << MSG::ERROR << " MuonID::init_neighbors - unable to get hash, exp/compact " + // << show_to_string(id, &wcontext) + // << " " << (std::string)m_full_wafer_range << endmsg; + // return (1); + // } + + // // index for the subsequent arrays + // unsigned short index = hash_id; + // assert (hash_id < m_prev_phi_wafer_vec.size()); + // assert (hash_id < m_next_phi_wafer_vec.size()); + // assert (hash_id < m_prev_eta_wafer_vec.size()); + // assert (hash_id < m_next_eta_wafer_vec.size()); + + // if (pphi) { + // // Get previous phi hash id + // ExpandedIdentifier expId = exp_id; + // expId[m_PHI_MODULE_INDEX] = previous_phi; + // Identifier id = wafer_id(expId[m_BARREL_EC_INDEX], + // expId[m_LAYER_DISK_INDEX], + // expId[m_PHI_MODULE_INDEX], + // expId[m_ETA_MODULE_INDEX], + // expId[m_SIDE_INDEX]); + // if (get_hash(id, hash_id, &wcontext)) { + // log << MSG::ERROR << " MuonID::init_neighbors - unable to get previous phi hash, exp/compact " << id.getString() << " " + // << endmsg; + // return (1); + // } + // m_prev_phi_wafer_vec[index] = hash_id; + // } + + // if (nphi) { + // // Get next phi hash id + // ExpandedIdentifier expId = exp_id; + // expId[m_PHI_MODULE_INDEX] = next_phi; + // Identifier id = wafer_id(expId[m_BARREL_EC_INDEX], + // expId[m_LAYER_DISK_INDEX], + // expId[m_PHI_MODULE_INDEX], + // expId[m_ETA_MODULE_INDEX], + // expId[m_SIDE_INDEX]); + // if (get_hash(id, hash_id, &wcontext)) { + // log << MSG::ERROR << " MuonID::init_neighbors - unable to get next phi hash, exp/compact " << id.getString() << + // " " << MSG::hex << id.getString() << MSG::dec << endmsg; + // return (1); + // } + // m_next_phi_wafer_vec[index] = hash_id; + // } + + // if (peta) { + // // Get previous eta hash id + // ExpandedIdentifier expId = exp_id; + // expId[m_ETA_MODULE_INDEX] = previous_eta; + // Identifier id = wafer_id(expId[m_BARREL_EC_INDEX], + // expId[m_LAYER_DISK_INDEX], + // expId[m_PHI_MODULE_INDEX], + // expId[m_ETA_MODULE_INDEX], + // expId[m_SIDE_INDEX]); + // if (get_hash(id, hash_id, &wcontext)) { + // log << MSG::ERROR << " MuonID::init_neighbors - unable to get previous eta hash, exp/compact " << id.getString() + // << " " << std::endl; + // return (1); + // } + // m_prev_eta_wafer_vec[index] = hash_id; + // } + + // if (neta) { + // // Get next eta hash id + // ExpandedIdentifier expId = exp_id; + // expId[m_ETA_MODULE_INDEX] = next_eta; + // Identifier id = wafer_id(expId[m_BARREL_EC_INDEX], + // expId[m_LAYER_DISK_INDEX], + // expId[m_PHI_MODULE_INDEX], + // expId[m_ETA_MODULE_INDEX], + // expId[m_SIDE_INDEX]); + // if (get_hash(id, hash_id, &wcontext)) { + // log << MSG::ERROR << " MuonID::init_neighbors - unable to get next eta hash, exp/compact " << id.getString() + // << " " << endmsg; + // return (1); + // } + // m_next_eta_wafer_vec[index] = hash_id; + // } + + +// std::cout << " MuonID::init_neighbors " +// << " phi, previous, next " << id[m_PHI_MODULE_INDEX] +// << " " << pphi +// << " " << previous_phi +// << " " << nphi +// << " " << next_phi +// << " eta, previous, next " << id[m_ETA_MODULE_INDEX] +// << " " << peta +// << " " << previous_eta +// << " " << neta +// << " " << next_eta +// << " id " << (std::string)(*first) +// << std::endl; + // } + // } + return (0); +} + + + +int +MuonID::initLevelsFromDict() +{ + + + MsgStream log(m_msgSvc, "MuonID"); + if(!m_dict) { + log << MSG::ERROR << " MuonID::initLevelsFromDict - dictionary NOT initialized " << endmsg; + return (1); + } + + // Find out which identifier field corresponds to each level. Use + // names to find each field/leve. + + m_SCINT_INDEX = 999; + m_MUON_INDEX = 999; + m_STATION_INDEX = 999; + m_PLATE_INDEX = 999; + m_PMT_INDEX = 999; + + // Save index to a Muon region for unpacking + ExpandedIdentifier id; + id << scint_field_value() << muon_field_value(); + if (m_dict->find_region(id, m_muon_region_index)) { + log << MSG::ERROR << "MuonID::initLevelsFromDict - unable to find muon region index: id, reg " + << (std::string)id << " " << m_muon_region_index + << endmsg; + return (1); + } + + // Find a Muon region + IdDictField* field = m_dict->find_field("subdet"); + if (field) { + m_SCINT_INDEX = field->m_index; + } + else { + log << MSG::ERROR << "MuonID::initLevelsFromDict - unable to find 'subdet' field " << endmsg; + return (1); + } + field = m_dict->find_field("part"); + if (field) { + m_MUON_INDEX = field->m_index; + } + else { + log << MSG::ERROR << "MuonID::initLevelsFromDict - unable to find 'part' field " << endmsg; + return (1); + } + field = m_dict->find_field("station"); + if (field) { + m_STATION_INDEX = field->m_index; + } + else { + log << MSG::ERROR << "MuonID::initLevelsFromDict - unable to find 'station' field " << endmsg; + return (1); + } + field = m_dict->find_field("plate"); + if (field) { + m_PLATE_INDEX = field->m_index; + } + else { + log << MSG::ERROR<< "MuonID::initLevelsFromDict - unable to find 'plate' field " << endmsg; + return (1); + } + field = m_dict->find_field("pmt"); + if (field) { + m_PMT_INDEX = field->m_index; + } + else { + log << MSG::ERROR << "MuonID::initLevelsFromDict - unable to find 'pmt' field " << endmsg; + return (1); + } + + // Set the field implementations + + const IdDictRegion& region = *m_dict->m_regions[m_muon_region_index]; + + m_scint_impl = region.m_implementation[m_SCINT_INDEX]; + m_muon_impl = region.m_implementation[m_MUON_INDEX]; + m_station_impl = region.m_implementation[m_STATION_INDEX]; + m_plate_impl = region.m_implementation[m_PLATE_INDEX]; + m_pmt_impl = region.m_implementation[m_PMT_INDEX]; + + if (m_msgSvc) { + log << MSG::DEBUG << "decode index and bit fields for each level: " << endmsg; + log << MSG::DEBUG << "scint " << m_scint_impl.show_to_string() << endmsg; + log << MSG::DEBUG << "muon " << m_muon_impl.show_to_string() << endmsg; + log << MSG::DEBUG << "station " << m_station_impl.show_to_string() << endmsg; + log << MSG::DEBUG << "plate " << m_plate_impl.show_to_string() << endmsg; + log << MSG::DEBUG << "pmt " << m_pmt_impl.show_to_string() << endmsg; + } + else { + std::cout << " DEBUG decode index and bit fields for each level: " << std::endl; + std::cout << " DEBUG scint " << m_scint_impl.show_to_string() << std::endl; + std::cout << " DEBUG muon " << m_muon_impl.show_to_string() << std::endl; + std::cout << " DEBUG station " << m_station_impl.show_to_string() << std::endl; + std::cout << " DEBUG plate " << m_plate_impl.show_to_string() << std::endl; + std::cout << " DEBUG pmt " << m_pmt_impl.show_to_string() << std::endl; + } + + std::cout << "scint " << m_scint_impl.decode_index() << " " + << (std::string)m_scint_impl.ored_field() << " " + << std::hex << m_scint_impl.mask() << " " + << m_scint_impl.zeroing_mask() << " " + << std::dec << m_scint_impl.shift() << " " + << m_scint_impl.bits() << " " + << m_scint_impl.bits_offset() + << std::endl; + std::cout << "muon" << m_muon_impl.decode_index() << " " + << (std::string)m_muon_impl.ored_field() << " " + << std::hex << m_muon_impl.mask() << " " + << m_muon_impl.zeroing_mask() << " " + << std::dec << m_muon_impl.shift() << " " + << m_muon_impl.bits() << " " + << m_muon_impl.bits_offset() + << std::endl; + std::cout << "station"<< m_station_impl.decode_index() << " " + << (std::string)m_station_impl.ored_field() << " " + << std::hex << m_station_impl.mask() << " " + << m_station_impl.zeroing_mask() << " " + << std::dec << m_station_impl.shift() << " " + << m_station_impl.bits() << " " + << m_station_impl.bits_offset() + << std::endl; + std::cout << "plate" << m_plate_impl.decode_index() << " " + << (std::string)m_plate_impl.ored_field() << " " + << std::hex << m_plate_impl.mask() << " " + << m_plate_impl.zeroing_mask() << " " + << std::dec << m_plate_impl.shift() << " " + << m_plate_impl.bits() << " " + << m_plate_impl.bits_offset() + << std::endl; + std::cout << "pmt" << m_pmt_impl.decode_index() << " " + << (std::string)m_pmt_impl.ored_field() << " " + << std::hex << m_pmt_impl.mask() << " " + << m_pmt_impl.zeroing_mask() << " " + << std::dec << m_pmt_impl.shift() << " " + << m_pmt_impl.bits() << " " + << m_pmt_impl.bits_offset() + << std::endl; + + return (0); +} + +MuonID::size_type +MuonID::plate_hash_max (void) const +{ + return m_plate_hash_max; +} + +MuonID::size_type +MuonID::pmt_hash_max (void) const +{ + return m_pmt_hash_max; +} + +MuonID::const_id_iterator MuonID::plate_begin (void) const +{ + return (m_plate_vec.begin()); +} + +MuonID::const_id_iterator MuonID::plate_end (void) const +{ + return (m_plate_vec.end()); +} + +MuonID::const_expanded_id_iterator MuonID::pmt_begin (void) const +{ + return (m_full_pmt_range.factory_begin()); +} + +MuonID::const_expanded_id_iterator MuonID::pmt_end (void) const +{ + return (m_full_pmt_range.factory_end()); +} + +// From hash get Identifier +int +MuonID::get_id (const IdentifierHash& hash_id, + Identifier& id, + const IdContext* context) const +{ + + int result = 1; + id.clear(); + + size_t begin = (context) ? context->begin_index(): 0; + // cannot get hash if end is 0: + size_t end = (context) ? context->end_index() : 0; + if (0 == begin) { + // No hashes yet for ids with prefixes + if (m_PLATE_INDEX == end) { + if (hash_id < (unsigned int)(m_plate_vec.end() - m_plate_vec.begin())) { + id = m_plate_vec[hash_id]; + result = 0; + } + } + else if (m_PMT_INDEX == end) { + // Do not know how to calculate strip id from hash yet!! + std::cout << "Do not know how to calculate pmt id from hash yet!!" << std::endl; + } + } + return (result); +} + +void +MuonID::get_expanded_id (const Identifier& id, + ExpandedIdentifier& exp_id, + const IdContext* context) const +{ + exp_id.clear(); + exp_id << scint_field_value() + << muon_field_value() + << station(id) + << plate(id); + if(!context || context->end_index() == m_PMT_INDEX) + { + exp_id << pmt(id); + } +} + +int +MuonID::get_hash (const Identifier& id, + IdentifierHash& hash_id, + const IdContext* context) const +{ + + // Get the hash code from either a vec (for plate) or calculate + // it (pmts). For the former, we convert to compact and call + // get_hash again. For the latter, we calculate the hash from the + // Identifier. + + int result = 1; + hash_id = 0; + size_t begin = (context) ? context->begin_index(): 0; + size_t end = (context) ? context->end_index() : 0; + if (0 == begin) { + // No hashes yet for ids with prefixes + if (m_PLATE_INDEX == end) { + hash_id = plate_hash(id); + if (hash_id.is_valid()) result = 0; + } + else if (context && context->end_index() == m_PMT_INDEX) { + // Must calculate for strip hash + ExpandedIdentifier new_id; + get_expanded_id(id, new_id); + hash_id = m_full_pmt_range.cardinalityUpTo(new_id); + result = 0; + } + } + return (result); +} + + +void +MuonID::test_plate_packing (void) const +{ + MsgStream log(m_msgSvc, "MuonID"); + + if (m_dict) { + + int nids = 0; + int nerr = 0; + IdContext context = plate_context(); + const_id_iterator first = m_plate_vec.begin(); + const_id_iterator last = m_plate_vec.end(); + for (; first != last; ++first, ++nids) { + Identifier id = (*first); + ExpandedIdentifier exp_id; + get_expanded_id(id, exp_id, &context); + Identifier new_id = plate_id(exp_id[m_STATION_INDEX], + exp_id[m_PLATE_INDEX]); + if (id != new_id) { + log << MSG::ERROR << "MuonID::test_plate_packing: new and old compacts not equal. New/old/expanded ids " + << MSG::hex << show_to_string(id) << " " << show_to_string(new_id) << " " << MSG::dec + << (std::string)exp_id << endmsg; + nerr++; + continue; + } + // check station id + if (!exp_id[m_PLATE_INDEX]) { + + Identifier new_id1 = station_id(exp_id[m_STATION_INDEX]); + if (id != new_id1) { + log << MSG::ERROR << "MuonID::test_plate_packing: new and old station ids not equal. New/old/expanded ids " + << MSG::hex << show_to_string(id) << " " << show_to_string(new_id1) << " " << MSG::dec + << (std::string)exp_id << endmsg; + nerr++; + continue; + } + } + } + + if (m_msgSvc) { + log << MSG::DEBUG << "MuonID::test_plate_packing: tested plate and station ids. nids, errors " + << nids << " " << nerr << endmsg; + } + else { + std::cout << " DEBUG MuonID::test_plate_packing: tested plate and station ids. nids, errors " + << nids << " " << nerr << std::endl; + } + + nids = 0; + context = pmt_context(); + const_expanded_id_iterator first_muon = pmt_begin(); + const_expanded_id_iterator last_muon = pmt_end(); + for (; first_muon != last_muon; ++first_muon, ++nids) { + // if (nids%10000 != 1) continue; + const ExpandedIdentifier& exp_id = *first_muon; + ExpandedIdentifier new_exp_id; + + Identifier id = plate_id(exp_id[m_STATION_INDEX], + exp_id[m_PLATE_INDEX]); + get_expanded_id(id, new_exp_id, &context); + if (exp_id[0] != new_exp_id[0] || + exp_id[1] != new_exp_id[1] || + exp_id[2] != new_exp_id[2] || + exp_id[3] != new_exp_id[3]) + { + log << MSG::ERROR << "MuonID::test_plate_packing: new and old ids not equal. New/old/compact ids " + << (std::string)new_exp_id << " " << (std::string)exp_id + << " " << show_to_string(id) << endmsg; + continue; + } + + Identifier pmtid ; + Identifier pmtid1 ; + pmtid = pmt_id ( + exp_id[m_STATION_INDEX], + exp_id[m_PLATE_INDEX], + exp_id[m_PMT_INDEX]); + + pmtid1 = pmt_id ( + station(pmtid), + plate(pmtid), + pmt(pmtid)); + + if (pmtid != pmtid1) { + log << MSG::ERROR << "MuonID::test_plate_packing: new and old pixel ids not equal. New/old ids " + << " " << show_to_string(pmtid1) << " " + << show_to_string(pmtid) << endmsg; + } + } + + if (m_msgSvc) { + log << MSG::DEBUG << "MuonID::test_plate_packing: Successful tested " + << nids << " ids. " + << endmsg; + } + else { + std::cout << " DEBUG MuonID::test_plate_packing: Successful tested " + << nids << " ids. " + << std::endl; + } + } + else { + log << MSG::ERROR << "MuonID::test_plate_packing: Unable to test plate packing - no dictionary has been defined. " + << endmsg; + } +} + diff --git a/Scintillator/ScintDetDescrCnv/ScintIdCnv/src/MuonIDDetDescrCnv.cxx b/Scintillator/ScintDetDescrCnv/ScintIdCnv/src/MuonIDDetDescrCnv.cxx new file mode 100644 index 0000000000000000000000000000000000000000..628c95d4af40b087a2d22cb162786921b022a603 --- /dev/null +++ b/Scintillator/ScintDetDescrCnv/ScintIdCnv/src/MuonIDDetDescrCnv.cxx @@ -0,0 +1,239 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +/*************************************************************************** + Scint DetDescrCnv package + ----------------------------------------- + ***************************************************************************/ + +//<<<<<< INCLUDES >>>>>> + +#include "MuonIDDetDescrCnv.h" + +#include "DetDescrCnvSvc/DetDescrConverter.h" +#include "DetDescrCnvSvc/DetDescrAddress.h" +#include "GaudiKernel/MsgStream.h" +#include "StoreGate/StoreGateSvc.h" + +#include "IdDictDetDescr/IdDictManager.h" +#include "ScintIdentifier/MuonID.h" + + +//<<<<<< PRIVATE DEFINES >>>>>> +//<<<<<< PRIVATE CONSTANTS >>>>>> +//<<<<<< PRIVATE TYPES >>>>>> +//<<<<<< PRIVATE VARIABLE DEFINITIONS >>>>>> +//<<<<<< PUBLIC VARIABLE DEFINITIONS >>>>>> +//<<<<<< CLASS STRUCTURE INITIALIZATION >>>>>> +//<<<<<< PRIVATE FUNCTION DEFINITIONS >>>>>> +//<<<<<< PUBLIC FUNCTION DEFINITIONS >>>>>> +//<<<<<< MEMBER FUNCTION DEFINITIONS >>>>>> + +//-------------------------------------------------------------------- + +long int +MuonIDDetDescrCnv::repSvcType() const +{ + return (storageType()); +} + +//-------------------------------------------------------------------- + +StatusCode +MuonIDDetDescrCnv::initialize() +{ + // First call parent init + StatusCode sc = DetDescrConverter::initialize(); + MsgStream log(msgSvc(), "MuonIDDetDescrCnv"); + log << MSG::DEBUG << "in initialize" << endmsg; + + if (sc.isFailure()) { + log << MSG::ERROR << "DetDescrConverter::initialize failed" << endmsg; + return sc; + } + + // The following is an attempt to "bootstrap" the loading of a + // proxy for MuonID into the detector store. However, + // MuonIDDetDescrCnv::initialize is NOT called by the conversion + // service. So for the moment, this cannot be use. Instead the + // DetDescrCnvSvc must do the bootstrap from a parameter list. + + +// // Add Scint_DetDescrManager proxy as entry point to the detector store +// // - this is ONLY needed for the manager of each system +// sc = addToDetStore(classID(), "MuonID"); +// if (sc.isFailure()) { +// log << MSG::FATAL << "Unable to add proxy for MuonID to the Detector Store!" << endmsg; +// return StatusCode::FAILURE; +// } else {} + + return StatusCode::SUCCESS; +} + +//-------------------------------------------------------------------- + +StatusCode +MuonIDDetDescrCnv::finalize() +{ + MsgStream log(msgSvc(), "MuonIDDetDescrCnv"); + log << MSG::DEBUG << "in finalize" << endmsg; + + return StatusCode::SUCCESS; +} + +//-------------------------------------------------------------------- + +StatusCode +MuonIDDetDescrCnv::createObj(IOpaqueAddress* pAddr, DataObject*& pObj) +{ + //StatusCode sc = StatusCode::SUCCESS; + MsgStream log(msgSvc(), "MuonIDDetDescrCnv"); + log << MSG::INFO << "in createObj: creating a MuonID helper object in the detector store" << endmsg; + + // Create a new MuonID + + DetDescrAddress* ddAddr; + ddAddr = dynamic_cast<DetDescrAddress*> (pAddr); + if(!ddAddr) { + log << MSG::FATAL << "Could not cast to DetDescrAddress." << endmsg; + return StatusCode::FAILURE; + } + + // Get the StoreGate key of this container. + std::string helperKey = *( ddAddr->par() ); + if ("" == helperKey) { + log << MSG::DEBUG << "No Helper key " << endmsg; + } + else { + log << MSG::DEBUG << "Helper key is " << helperKey << endmsg; + } + + + // get DetectorStore service + StoreGateSvc * detStore; + StatusCode status = serviceLocator()->service("DetectorStore", detStore); + if (status.isFailure()) { + log << MSG::FATAL << "DetectorStore service not found !" << endmsg; + return StatusCode::FAILURE; + } else {} + + // Get the dictionary manager from the detector store + const IdDictManager* idDictMgr; + status = detStore->retrieve(idDictMgr, "IdDict"); + if (status.isFailure()) { + log << MSG::FATAL << "Could not get IdDictManager !" << endmsg; + return StatusCode::FAILURE; + } + else { + log << MSG::DEBUG << " Found the IdDictManager. " << endmsg; + } + + // Only create new helper if it is the first pass or if there is a + // change in the the file or tag + bool initHelper = false; + + const IdDictMgr* mgr = idDictMgr->manager(); + + // Internal Scint id tag + std::string scintIDTag = mgr->tag(); + + // DoChecks flag + bool doChecks = mgr->do_checks(); + + IdDictDictionary* dict = mgr->find_dictionary("Scintillator"); + if (!dict) { + log << MSG::ERROR + << "unable to find idDict for Scintillator" + << endmsg; + return StatusCode::FAILURE; + } + + // File to be read for Scint ids + std::string scintIDFileName = dict->file_name(); + + // Tag of RDB record for Scint ids + std::string scintIdDictTag = dict->dict_tag(); + + + if (m_muonId) { + + // Muon id helper already exists - second pass. Check for a + // change + if (scintIDTag != m_scintIDTag) { + // Internal Scint id tag + initHelper = true; + log << MSG::DEBUG << " Changed internal Scint id tag: " + << scintIDTag << endmsg; + } + if (scintIDFileName != m_scintIDFileName) { + // File to be read for Scint ids + initHelper = true; + log << MSG::DEBUG << " Changed ScintFileName:" + << scintIDFileName << endmsg; + } + if (scintIdDictTag != m_scintIdDictTag) { + // Tag of RDB record for Scint ids + initHelper = true; + log << MSG::DEBUG << " Changed ScintIdDictTag: " + << scintIdDictTag + << endmsg; + } + if (doChecks != m_doChecks) { + // DoChecks flag + initHelper = true; + log << MSG::DEBUG << " Changed doChecks flag: " + << doChecks + << endmsg; + } + } + else { + // create the helper + m_muonId = new MuonID; + initHelper = true; + // add in message service for printout + m_muonId->setMessageSvc(msgSvc()); + } + + if (initHelper) { + if (idDictMgr->initializeHelper(*m_muonId)) { + log << MSG::ERROR << "Unable to initialize MuonID" << endmsg; + return StatusCode::FAILURE; + } + // Save state: + m_scintIDTag = scintIDTag; + m_scintIDFileName = scintIDFileName; + m_scintIdDictTag = scintIdDictTag; + m_doChecks = doChecks; + } + + // Pass a pointer to the container to the Persistency service by reference. + pObj = SG::asStorable(m_muonId); + + return StatusCode::SUCCESS; + +} + +//-------------------------------------------------------------------- + +long +MuonIDDetDescrCnv::storageType() +{ + return DetDescr_StorageType; +} + +//-------------------------------------------------------------------- +const CLID& +MuonIDDetDescrCnv::classID() { + return ClassID_traits<MuonID>::ID(); +} + +//-------------------------------------------------------------------- +MuonIDDetDescrCnv::MuonIDDetDescrCnv(ISvcLocator* svcloc) + : + DetDescrConverter(ClassID_traits<MuonID>::ID(), svcloc), + m_muonId(0), + m_doChecks(false) + +{} + diff --git a/Scintillator/ScintDetDescrCnv/ScintIdCnv/src/MuonIDDetDescrCnv.h b/Scintillator/ScintDetDescrCnv/ScintIdCnv/src/MuonIDDetDescrCnv.h new file mode 100644 index 0000000000000000000000000000000000000000..9be6e056be5290194d856d045ae18e29bc444877 --- /dev/null +++ b/Scintillator/ScintDetDescrCnv/ScintIdCnv/src/MuonIDDetDescrCnv.h @@ -0,0 +1,71 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +/*************************************************************************** + Scint DetDescrCnv package + ----------------------------------------- + ***************************************************************************/ + +#ifndef SCINTIDCNV_MUONIDDETDESCRCNV_H +#define SCINTIDCNV_MUONIDDETDESCRCNV_H + +//<<<<<< INCLUDES >>>>>> + +#include "DetDescrCnvSvc/DetDescrConverter.h" + +//<<<<<< PUBLIC DEFINES >>>>>> +//<<<<<< PUBLIC CONSTANTS >>>>>> +//<<<<<< PUBLIC TYPES >>>>>> + +class MuonID; + +//<<<<<< PUBLIC VARIABLES >>>>>> +//<<<<<< PUBLIC FUNCTIONS >>>>>> +//<<<<<< CLASS DECLARATIONS >>>>>> + + +/** + ** This class is a converter for the MuonID an IdHelper which is + ** stored in the detector store. This class derives from + ** DetDescrConverter which is a converter of the DetDescrCnvSvc. + ** + **/ + +class MuonIDDetDescrCnv: public DetDescrConverter { + +public: + virtual long int repSvcType() const; + virtual StatusCode initialize(); + virtual StatusCode finalize(); + virtual StatusCode createObj(IOpaqueAddress* pAddr, DataObject*& pObj); + + // Storage type and class ID (used by CnvFactory) + static long storageType(); + static const CLID& classID(); + + MuonIDDetDescrCnv(ISvcLocator* svcloc); + +private: + /// The helper - only will create it once + MuonID* m_muonId; + + /// File to be read for Scint ids + std::string m_scintIDFileName; + + /// Tag of RDB record for Scint ids + std::string m_scintIdDictTag; + + /// Internal Scint id tag + std::string m_scintIDTag; + + /// Whether or not + bool m_doChecks; + +}; + + +//<<<<<< INLINE PUBLIC FUNCTIONS >>>>>> +//<<<<<< INLINE MEMBER FUNCTIONS >>>>>> + +#endif // SCINTIDCNV_MUONIDDETDESCRCNV_H diff --git a/Scintillator/ScintDetDescrCnv/ScintIdCnv/src/ScintIdCnv_entries.cxx b/Scintillator/ScintDetDescrCnv/ScintIdCnv/src/ScintIdCnv_entries.cxx index 0b99ec46b38a725159e9ae7f914d7df3b99b2178..0c0a07e988699d48a4002c897c7370f2a85a6ce2 100644 --- a/Scintillator/ScintDetDescrCnv/ScintIdCnv/src/ScintIdCnv_entries.cxx +++ b/Scintillator/ScintDetDescrCnv/ScintIdCnv/src/ScintIdCnv_entries.cxx @@ -6,6 +6,7 @@ #include "VetoNuIDDetDescrCnv.h" #include "TriggerIDDetDescrCnv.h" #include "PreshowerIDDetDescrCnv.h" +#include "MuonIDDetDescrCnv.h" // DECLARE_CONVERTER(SCT_IDDetDescrCnv) // DECLARE_CONVERTER(PixelIDDetDescrCnv) @@ -15,3 +16,4 @@ DECLARE_CONVERTER(VetoIDDetDescrCnv) DECLARE_CONVERTER(VetoNuIDDetDescrCnv) DECLARE_CONVERTER(TriggerIDDetDescrCnv) DECLARE_CONVERTER(PreshowerIDDetDescrCnv) +DECLARE_CONVERTER(MuonIDDetDescrCnv) diff --git a/Tracker/TrackerRecAlgs/NoisyStripFinder/share/NoisyStripFinderJob.py b/Tracker/TrackerRecAlgs/NoisyStripFinder/share/NoisyStripFinderJob.py index 6235c83623c8be6434af009a71aff25b624f91c1..778893423abac7b678dd58e3a57f1e04e3eb0aa5 100755 --- a/Tracker/TrackerRecAlgs/NoisyStripFinder/share/NoisyStripFinderJob.py +++ b/Tracker/TrackerRecAlgs/NoisyStripFinder/share/NoisyStripFinderJob.py @@ -40,7 +40,7 @@ for filename in args.file: configFlags = initConfigFlags() configFlags.Input.Files = args.file -configFlags.IOVDb.GlobalTag = "OFLCOND-FASER-04" +configFlags.IOVDb.GlobalTag = "OFLCOND-FASER-05" #configFlags.IOVDb.DatabaseInstance = "OFLP200" configFlags.IOVDb.DatabaseInstance = "CONDBR3" configFlags.Input.ProjectName = "data22" diff --git a/Tracking/Acts/FaserActsKalmanFilter/src/GhostBusters.cxx b/Tracking/Acts/FaserActsKalmanFilter/src/GhostBusters.cxx index f191ba2c72d04c5668590abcdd320a0846ba41be..14ae6f0d4f95c17bb69d384496e2edf1f7cb7358 100644 --- a/Tracking/Acts/FaserActsKalmanFilter/src/GhostBusters.cxx +++ b/Tracking/Acts/FaserActsKalmanFilter/src/GhostBusters.cxx @@ -34,7 +34,7 @@ StatusCode GhostBusters::initialize() { StatusCode GhostBusters::execute(const EventContext &ctx) const { m_event_number = ctx.eventID().event_number(); - ATH_MSG_INFO("GHOSTBUSTING Event Number = " << m_event_number); + ATH_MSG_DEBUG("GHOSTBUSTING Event Number = " << m_event_number); SG::WriteHandle outputTrackCollection {m_outputTrackCollection, ctx}; std::unique_ptr<TrackCollection> outputTracks = std::make_unique<TrackCollection>(); @@ -64,21 +64,21 @@ StatusCode GhostBusters::execute(const EventContext &ctx) const { double meanY = 0.5 * (minY + maxY); double deltaX = deltaY / (2 * std::tan(0.02)); - ATH_MSG_INFO("maxX = " << maxX); - ATH_MSG_INFO("maxY = " << maxY); - ATH_MSG_INFO("minX = " << minX); - ATH_MSG_INFO("minY = " << minY); - ATH_MSG_INFO("deltaY = " << deltaY); - ATH_MSG_INFO("meanX = " << meanX); - ATH_MSG_INFO("meanY = " << meanY); - ATH_MSG_INFO("deltaX = " << deltaX); + ATH_MSG_DEBUG("maxX = " << maxX); + ATH_MSG_DEBUG("maxY = " << maxY); + ATH_MSG_DEBUG("minX = " << minX); + ATH_MSG_DEBUG("minY = " << minY); + ATH_MSG_DEBUG("deltaY = " << deltaY); + ATH_MSG_DEBUG("meanX = " << meanX); + ATH_MSG_DEBUG("meanY = " << meanY); + ATH_MSG_DEBUG("deltaX = " << deltaX); - ATH_MSG_INFO("yLowerBound = " << meanY - m_yTolerance * deltaY); - ATH_MSG_INFO("yUpperBound = " << meanY + m_yTolerance * deltaY); - ATH_MSG_INFO("xLeftLowerBound = " << meanX - (1 + m_xTolerance) * deltaX); - ATH_MSG_INFO("xLeftUpperBound = " << meanX - (1 - m_xTolerance) * deltaX); - ATH_MSG_INFO("xRightLowerBound = " << meanX + (1 - m_xTolerance) * deltaX); - ATH_MSG_INFO("xRightUpperBound = " << meanX + (1 + m_xTolerance) * deltaX); + ATH_MSG_DEBUG("yLowerBound = " << meanY - m_yTolerance * deltaY); + ATH_MSG_DEBUG("yUpperBound = " << meanY + m_yTolerance * deltaY); + ATH_MSG_DEBUG("xLeftLowerBound = " << meanX - (1 + m_xTolerance) * deltaX); + ATH_MSG_DEBUG("xLeftUpperBound = " << meanX - (1 - m_xTolerance) * deltaX); + ATH_MSG_DEBUG("xRightLowerBound = " << meanX + (1 - m_xTolerance) * deltaX); + ATH_MSG_DEBUG("xRightUpperBound = " << meanX + (1 + m_xTolerance) * deltaX); @@ -89,10 +89,10 @@ StatusCode GhostBusters::execute(const EventContext &ctx) const { ((segment.x() > meanX + (1 - m_xTolerance) * deltaX) && (segment.x() < meanX + (1 + m_xTolerance) * deltaX))); if (isGhost) segment.setGhost(); if (not isGhost && segment.size() >= 5) nGoodSegments++; - ATH_MSG_INFO("Segment Y = " << segment.y()); - ATH_MSG_INFO("Segment X = " << segment.x()); - ATH_MSG_INFO("Segment isGhost = " << isGhost); - ATH_MSG_INFO("nGoodSegments = " << nGoodSegments); + ATH_MSG_DEBUG("Segment Y = " << segment.y()); + ATH_MSG_DEBUG("Segment X = " << segment.x()); + ATH_MSG_DEBUG("Segment isGhost = " << isGhost); + ATH_MSG_DEBUG("nGoodSegments = " << nGoodSegments); } for (const Segment &segment : stationSegments) { m_x = segment.x(); @@ -101,16 +101,16 @@ StatusCode GhostBusters::execute(const EventContext &ctx) const { m_chi2 = segment.chi2(); m_station = segment.station(); m_size = segment.size(); - ATH_MSG_INFO("m_x = " << m_x); - ATH_MSG_INFO("m_y = " << m_y); - ATH_MSG_INFO("m_z = " << m_z); + ATH_MSG_DEBUG("m_x = " << m_x); + ATH_MSG_DEBUG("m_y = " << m_y); + ATH_MSG_DEBUG("m_z = " << m_z); // m_majorityHits = segment.majorityHits(); m_isGhost = segment.isGhost(); - ATH_MSG_INFO("m_isGhost = " << m_isGhost); - ATH_MSG_INFO("nGoodSegments = " << nGoodSegments); - ATH_MSG_INFO("segment.size() = " << segment.size()); + ATH_MSG_DEBUG("m_isGhost = " << m_isGhost); + ATH_MSG_DEBUG("nGoodSegments = " << nGoodSegments); + ATH_MSG_DEBUG("segment.size() = " << segment.size()); // if (nGoodSegments >= 2 && segment.size() == 4) m_isGhost = true; - ATH_MSG_INFO("m_isGhost after if statement = " << m_isGhost); + ATH_MSG_DEBUG("m_isGhost after if statement = " << m_isGhost); m_tree->Fill(); if (segment.isGhost()) continue; // if (nGoodSegments >= 2 && segment.size() == 4) continue; diff --git a/Waveform/WaveEventCnv/WaveByteStream/src/RawWaveformDecoderTool.cxx b/Waveform/WaveEventCnv/WaveByteStream/src/RawWaveformDecoderTool.cxx index d9728fa086b226b417d7af130431131f58d2d13b..5a79650dac1741a028dee4d7e8639506a91c3366 100644 --- a/Waveform/WaveEventCnv/WaveByteStream/src/RawWaveformDecoderTool.cxx +++ b/Waveform/WaveEventCnv/WaveByteStream/src/RawWaveformDecoderTool.cxx @@ -97,10 +97,12 @@ RawWaveformDecoderTool::convert(const DAQFormats::EventFull* re, ATH_MSG_DEBUG("Found valid digitizer0 fragment"); } - if (!digitizer1) { // Will happen in data before 2024 - ATH_MSG_INFO("Failed to find digitizer1 fragment in raw event!"); + if (cable_map.size() > 16) + ATH_MSG_WARNING("Failed to find digitizer1 fragment in raw event!"); + else + ATH_MSG_DEBUG("Failed to find digitizer1 fragment in raw event!"); } else { if (!digitizer1->valid()) { ATH_MSG_WARNING("Found invalid digitizer1 fragment:\n" << *digitizer1); @@ -109,12 +111,24 @@ RawWaveformDecoderTool::convert(const DAQFormats::EventFull* re, } } + // Check if boards are out of sync + int timing_shift = 0; + if (digitizer1 && digitizer1->valid()) { + if (digitizer1->trigger_time_tag() != digitizer0->trigger_time_tag()) { + // These are unsigned integers, make them ints so we can get -1 + timing_shift = int(digitizer1->trigger_time_tag()) - int(digitizer0->trigger_time_tag()); + ATH_MSG_DEBUG("Digi1 - Digi0 trigger time: " << timing_shift); + } + } + // Detector type to match in first element of cable map std::string det_type; if (key == std::string("CaloWaveforms")) { det_type = std::string("calo"); } else if (key == std::string("Calo2Waveforms")) { det_type = std::string("calo2"); + } else if (key == std::string("CaloNuWaveforms")) { + det_type = std::string("calonu"); } else if (key == std::string("VetoWaveforms")) { det_type = std::string("veto"); } else if (key == std::string("VetoNuWaveforms")) { @@ -123,6 +137,8 @@ RawWaveformDecoderTool::convert(const DAQFormats::EventFull* re, det_type = std::string("trigger"); } else if (key == std::string("PreshowerWaveforms")) { det_type = std::string("preshower"); + } else if (key == std::string("MuonWaveforms")) { + det_type = std::string("muon"); } else if (key == std::string("ClockWaveforms")) { det_type = std::string("clock"); } else { @@ -142,15 +158,28 @@ RawWaveformDecoderTool::convert(const DAQFormats::EventFull* re, ATH_MSG_DEBUG("Converting channel "+std::to_string(channel)+" for "+key); int chan = channel; + int shift = 0; digitizer = digitizer0; if (channel > 15) { chan = channel-16; digitizer = digitizer1; + shift = timing_shift; // Only apply timing shift to 2nd digitizer + } + + // Check if digitizer is OK + if (!digitizer) { + ATH_MSG_WARNING("Channel " << channel << " has missing digitizer!"); + continue; + } + + if (!digitizer->valid()) { + ATH_MSG_WARNING("Channel " << channel << " has invalid digitizer!"); + continue; } // Check if this has data if (!digitizer->channel_has_data(chan)) { - ATH_MSG_DEBUG("Channel " << channel << " has no data - skipping!"); + ATH_MSG_WARNING("Channel " << channel << " has no data - skipping!"); continue; } @@ -184,6 +213,9 @@ RawWaveformDecoderTool::convert(const DAQFormats::EventFull* re, // Set ADC range wfm->setRange(range_map.at(channel)); + // Set timing shift + wfm->setTriggerOffset(shift); + container->push_back(wfm); // Sanity check diff --git a/Waveform/WaveRawEvent/WaveRawEvent/RawWaveform.h b/Waveform/WaveRawEvent/WaveRawEvent/RawWaveform.h index a1f42f6e86db846ea544daedb482ba8aba8fbdf5..d66250b56ec1c174774348142749523fa3b87e71 100644 --- a/Waveform/WaveRawEvent/WaveRawEvent/RawWaveform.h +++ b/Waveform/WaveRawEvent/WaveRawEvent/RawWaveform.h @@ -58,7 +58,8 @@ public: unsigned int event_counter() const; unsigned int trigger_time_tag() const; unsigned int n_samples() const; - + int trigger_offset() const; + // Waveform data unsigned int channel() const; const std::vector<unsigned int>& adc_counts() const; @@ -94,6 +95,7 @@ public: void setChannel(unsigned int chan) {m_channel = chan;} void setSamples(unsigned int samp) {m_samples = samp;} void setCounts(const std::vector<unsigned int>& counts) {m_adc_counts = counts;} + void setTriggerOffset(int off) {m_trigger_offset = off;} void setRange(float range) {m_range = range;} @@ -114,7 +116,8 @@ private: Identifier32 m_ID; - float m_range; + float m_range; + int m_trigger_offset; }; @@ -158,6 +161,9 @@ RawWaveform::identify32() const { return m_ID; } inline float RawWaveform::range() const { return m_range; } +inline int +RawWaveform::trigger_offset() const { return m_trigger_offset; } + std::ostream &operator<<(std::ostream &out, const RawWaveform &wfm); diff --git a/Waveform/WaveRawEvent/src/RawWaveform.cxx b/Waveform/WaveRawEvent/src/RawWaveform.cxx index 64c401dfad6a9fe9794737a953eca31eff110bc1..d13617a5c9393cca1d89b1afe07f39a1f1577f00 100644 --- a/Waveform/WaveRawEvent/src/RawWaveform.cxx +++ b/Waveform/WaveRawEvent/src/RawWaveform.cxx @@ -18,7 +18,8 @@ RawWaveform::RawWaveform( ) : m_channel(0), m_adc_counts(), m_ID(0xffff), - m_range(2.) + m_range(2.), + m_trigger_offset(0) { } diff --git a/Waveform/WaveRecAlgs/python/WaveRecAlgsConfig.py b/Waveform/WaveRecAlgs/python/WaveRecAlgsConfig.py index b1b586585f93de7142951e7b293e0a3f25ef0b88..c836a33481d4c0f8ecccca9feab5b3d88a314ac5 100644 --- a/Waveform/WaveRecAlgs/python/WaveRecAlgsConfig.py +++ b/Waveform/WaveRecAlgs/python/WaveRecAlgsConfig.py @@ -25,6 +25,7 @@ def WaveformReconstructionCfg(flags): acc.merge(WaveformHitRecCfg(flags, "CaloWaveformRecAlg", "Calo")) # Make preshower/veto window 200 ns wide (100 digitizer clock ticks) + # Adjust baseline range for early signals (CaloNu, VetoNu) acc.merge(WaveformHitRecCfg(flags, "VetoWaveformRecAlg", "Veto", FitWindowWidth=100 )) acc.merge(WaveformHitRecCfg(flags, "PreshowerWaveformRecAlg", "Preshower", FitWindowWidth=100 )) @@ -33,13 +34,17 @@ def WaveformReconstructionCfg(flags): if flags.Input.isMC: print("Calo2WaveformRecAlg diabled for MC in WaveformReconstructionCfg!") else: + # 2024/25 detectors (not in MC yet) acc.merge(WaveformHitRecCfg(flags, "Calo2WaveformRecAlg", "Calo2")) + acc.merge(WaveformHitRecCfg(flags, "CaloNuWaveformRecAlg", "CaloNu", BaselineSampleHi=50)) + acc.merge(WaveformHitRecCfg(flags, "MuonWaveformRecAlg", "Muon", FitWindowWidth=100, BaselineSampleHi=60)) # Make preshower window 200 ns wide (value in digitizer clock ticks) + # Limit range to determine baseline for early channels acc.merge(WaveformHitRecCfg(flags, "VetoWaveformRecAlg", "Veto", FitWindowWidth=100 )) - acc.merge(WaveformHitRecCfg(flags, "PreshowerWaveformRecAlg", "Preshower", FitWindowWidth=100 )) + acc.merge(WaveformHitRecCfg(flags, "PreshowerWaveformRecAlg", "Preshower", FitWindowWidth=100, BaselineSampleHi=60 )) acc.merge(WaveformHitRecCfg(flags, "TriggerWaveformRecAlg", "Trigger", FitWindowWidth=100)) - acc.merge(WaveformHitRecCfg(flags, "VetoNuWaveformRecAlg", "VetoNu", FitWindowWidth=100)) + acc.merge(WaveformHitRecCfg(flags, "VetoNuWaveformRecAlg", "VetoNu", FitWindowWidth=100, BaselineSampleHi=60)) acc.merge(WaveformTimingCfg(flags)) @@ -75,7 +80,8 @@ def WaveformHitRecCfg(flags, name="WaveformRecAlg", source="", **kwargs): # Remove arguments intended for WaveRecTool if "PeakThreshold" in kwargs: kwargs.pop("PeakThreshold") if "FitWindowWidth" in kwargs: kwargs.pop("FitWindowWidth") - + if "BaselineSampleHi" in kwargs: kwargs.pop("BaselineSampleHi") + kwargs.setdefault("WaveformContainerKey", source+"Waveforms") kwargs.setdefault("WaveformHitContainerKey", source+"WaveformHits") kwargs.setdefault("WaveformReconstructionTool", tool) diff --git a/Waveform/WaveRecTools/src/ClockReconstructionTool.cxx b/Waveform/WaveRecTools/src/ClockReconstructionTool.cxx index 825cc755862200c0dd008eaf3c273cb23b37f83a..26a4dd9a435726a9e2177135dd72b5cca147f91e 100644 --- a/Waveform/WaveRecTools/src/ClockReconstructionTool.cxx +++ b/Waveform/WaveRecTools/src/ClockReconstructionTool.cxx @@ -147,6 +147,13 @@ ClockReconstructionTool::reconstruct(const RawWaveform& raw_wave, if (m_checkResult) checkResult(raw_wave, clockdata); + // Finally, set the time offset if the 2nd digitizer triggered late + if (raw_wave.trigger_offset() >= 1) { + clockdata->set_time_offset(-16.); // 16 ns + } else { + clockdata->set_time_offset(0.); + } + return StatusCode::SUCCESS; } diff --git a/Waveform/WaveRecTools/src/WaveformReconstructionTool.cxx b/Waveform/WaveRecTools/src/WaveformReconstructionTool.cxx index 1caf49d4a3be081da8c8b8339324125ee6df788b..e69a6fb8440a312505b2d8c8a31b69825b1a4d42 100644 --- a/Waveform/WaveRecTools/src/WaveformReconstructionTool.cxx +++ b/Waveform/WaveRecTools/src/WaveformReconstructionTool.cxx @@ -91,19 +91,27 @@ WaveformReconstructionTool::reconstructPrimary( float trigger_time = m_timingTool->nominalTriggerTime(); // Set range for windowed data in digitizer samples - float offset = m_timingTool->triggerTimeOffset(wave.channel()); + float trigger_offset = m_timingTool->triggerTimeOffset(wave.channel()); - int lo_edge = int((trigger_time+offset)/2.) + m_windowStart; - int hi_edge = int((trigger_time+offset)/2.) + m_windowStart + m_windowWidth; + + int lo_edge = int((trigger_time+trigger_offset)/2.) + m_windowStart; + int hi_edge = int((trigger_time+trigger_offset)/2.) + m_windowStart + m_windowWidth; if (hi_edge >= int(wave.size())) { // This likely means we have the wrong digitizer range ATH_MSG_WARNING("Found channel " << wave.channel() << " with low edge: " << lo_edge << " hi edge: " << hi_edge << " > wave.size() " << wave.size()); - ATH_MSG_WARNING(" trigger_time + offset: " << (trigger_time+offset) << " => " << int((trigger_time+offset)/2.)); + ATH_MSG_WARNING(" trigger_time + trigger_offset: " << (trigger_time+trigger_offset) << " => " << int((trigger_time+trigger_offset)/2.)); newhit->set_status_bit(xAOD::WaveformStatus::WAVEFORM_INVALID); return StatusCode::SUCCESS; } + // Adjust window time if 2nd digitizer triggered late + // Waveform will arrive early by 16ns + if (wave.trigger_offset() >= 1) { + lo_edge -= 8; + hi_edge -= 8; + } + // Fill raw hit values fillRawHitValues(wave, lo_edge, hi_edge, newhit); @@ -309,7 +317,7 @@ WaveformReconstructionTool::setLocalTime(const xAOD::WaveformClock* clock, } float trigger_time = m_timingTool->nominalTriggerTime(); - float offset; + float trigger_offset; // Should actually find the time of the trigger here // and set bcid time offset from that @@ -317,17 +325,28 @@ WaveformReconstructionTool::setLocalTime(const xAOD::WaveformClock* clock, for( const auto& hit : *container) { // - // Find time from clock + // Do we need to add an additional 16ns shift for the second + // digitizer triggering early? + float digi_offset = 0.; + if (hit->status_bit(xAOD::WaveformStatus::TIMING_SHIFTED)) { + digi_offset = -16.; + } + + // Set time with respect to nominal trigger + trigger_offset = m_timingTool->triggerTimeOffset(hit->channel()); + hit->set_trigger_time(hit->localtime() - (trigger_time + trigger_offset + digi_offset)); + + // + // Find time from LHC clock + // Take out any relative offsets to align signals, but not the trigger_time + // This will also correct for the trigger time variation if (clock_valid) { - hit->set_bcid_time(clock->time_from_clock(hit->localtime())); + hit->set_bcid_time(clock->time_from_clock(hit->localtime()-(trigger_offset + digi_offset))); } else { hit->set_status_bit(xAOD::WaveformStatus::CLOCK_INVALID); hit->set_bcid_time(-1.); } - // Also set time with respect to nominal trigger - offset = m_timingTool->triggerTimeOffset(hit->channel()); - hit->set_trigger_time(hit->localtime() - (trigger_time + offset)); } return StatusCode::SUCCESS; @@ -371,7 +390,7 @@ void WaveformReconstructionTool::fillRawHitValues(const RawWaveform& wave, int lo_edge, int hi_edge, xAOD::WaveformHit* hit) const { - + // First, make sure we don't overflow the waveform range if (lo_edge < 0) lo_edge = 0; if (hi_edge >= int(wave.size())) hi_edge = wave.size() - 1; @@ -406,6 +425,12 @@ WaveformReconstructionTool::fillRawHitValues(const RawWaveform& wave, hit->set_raw_peak(raw.peak); hit->set_raw_integral(raw.integral); + // Indicate digitizer timing shift + if (wave.trigger_offset() >= 1) { + hit->set_status_bit(xAOD::WaveformStatus::TIMING_SHIFTED); + } + + } // Reconstruct a hit from the RawWaveform in the range specified @@ -693,6 +718,7 @@ WaveformReconstructionTool::findRawHitValues(const std::vector<float> time, cons double sum2 = 0.; for (unsigned int i=0; i<time.size(); i++) { //ATH_MSG_DEBUG("findRawHitValues Time: " << time[i] << " Wave: " << wave[i]); + if (wave[i] <= 0.) continue; // Don't sum negative values, causes problems with RMS tot += wave[i]; sum += time[i] * wave[i]; sum2 += time[i] * time[i] * wave[i]; diff --git a/Waveform/WaveformConditions/WaveCondUtils/scripts/makeTimingDB.py b/Waveform/WaveformConditions/WaveCondUtils/scripts/makeTimingDB.py index 640b684042565ad09468a951f2b83923e4bb217b..1c02b6edf6537eb43a3cf7efbde1be1b3ea63c5e 100755 --- a/Waveform/WaveformConditions/WaveCondUtils/scripts/makeTimingDB.py +++ b/Waveform/WaveformConditions/WaveCondUtils/scripts/makeTimingDB.py @@ -58,7 +58,13 @@ offset_data = { # IFT and VetoNu installed 6525: [ -10., -10., -10., -10., -25., -25., 0., 0., 0., 0., 0., 0., 18., 18., 0., 0. ], # 2024, add 2nd digitizer - 13847: [ -10., -10., -10., -10., -25., -25., 0., 0., 0., 0., 0., 0., 18., 18., 0., 0., -10., -10., -10., -10. ] + 13847: [ -10., -10., -10., -10., + -25., -25., 0., 0., + 0., 0., 0., 0., + 18., 18., 0., 0., + + -10., -10., -10., -10. ] + } attr_list_desc = '<timeStamp>run-lumi</timeStamp><addrHeader><address_header service_type="71" clid="40774348" /></addrHeader><typeName>AthenaAttributeList</typeName>' diff --git a/Waveform/WaveformConditions/WaveCondUtils/scripts/makeTimingOffsetDB.py b/Waveform/WaveformConditions/WaveCondUtils/scripts/makeTimingOffsetDB.py new file mode 100755 index 0000000000000000000000000000000000000000..73519ba36525dfaeb607854630d1ab3c5ec9e02d --- /dev/null +++ b/Waveform/WaveformConditions/WaveCondUtils/scripts/makeTimingOffsetDB.py @@ -0,0 +1,208 @@ +#!/bin/env python + +# Requires python 3.8 or higher +# +# Can test results with +# AtlCoolConsole.py "sqlite://;schema=waveform_reco.db;dbname=OFLP200" +# +# This script only sets the timing offset +# +filename = 'timing_offset.db' +#filename = 'ALLP200.db' + +# offset_channels = 20 + +# Run +# 0 - initial data +# 3395 - Testbeam +# + +ehn1_offsets = [ -20., -20., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0. ] +ti12_offsets = [ -20., -20., -20., -20., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0. ] + +offset_data = { + 0: [ 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0. ], +# Initial TI12 + 1324: [ -10., -10., -10., -10., 0., 0., 0., 0., 0., 0., 0., 0., 18., 18., 0., 0. ], +# Testbeam geometry + 3247: [ -10., -10., -10., -10., -10., -10., 15., 15., -20., -20., 0., 0., 0., 0., 0., 0. ], +# TI12 + 4272: ti12_offsets, +# EHN1 (interleaved with TI12 running) + 4360: ehn1_offsets, + 4399: ti12_offsets, + 4409: ehn1_offsets, + 4411: ti12_offsets, + 4429: ehn1_offsets, + 4439: ti12_offsets, + 4876: ehn1_offsets, + 4892: ti12_offsets, + 4904: ehn1_offsets, + 4912: ti12_offsets, + 4954: ehn1_offsets, + 4989: ti12_offsets, + 4991: ehn1_offsets, + 4993: ti12_offsets, + 4996: ehn1_offsets, + 4997: ti12_offsets, + 5042: ehn1_offsets, + 5050: ti12_offsets, +# IFT and VetoNu installed + 6525: [ -10., -10., -10., -10., -35., -35., 0., 0., + 0., 0., 0., 0., 18., 18., 0., 0. ], +# 2024, add 2nd digitizer + 13847: [ -4., -4., -4., -4., -35., -35., 0., 0., + 0., 0., 0., 0., 18., 18., 0., 0., + -4., -4., -4., -4. ], +# 2024, add CaloNu + 15821: [ -4., -4., -4., -4., -35., -35., 0., 0., + 0., 0., 0., 0., 18., 18., 0., 0., + -4., -4., -4., -4., -48., -48., -48., -48. ], +# Move CaloNu to trigger + 15845: [ -4., -4., -4., -4., -35., -35., -48., -48., + 0., 0., 0., 0., 18., 18., -48., -48., + -4., -4., -4., -4., 0., 0., 0., 0. ], +# CaloNu removed + 16925: [ -4., -4., -4., -4., -35., -35., 0., 0., + 0., 0., 0., 0., 18., 18., 0., 0., + -4., -4., -4., -4., ], +# 2025 startup + 18193: [ -4., -4., -4., -4., -35., -35., 0., 0., + 0., 0., 0., 0., 18., 18., 0., 0., + -4., -4., -4., -4., 0., 0., 0., 0., + -35., -35., 0., 0.], +# Fix 2025 startup +# +# VetoNu (4,5) is early +# Preshower (12, 13, 24, 25) is also now early +# Muon (26, 27) is 20 ns late + 18195: [ -4., -4., -4., -4., -35., -35., 0., 0., + 0., 0., 0., 0., -24., -24., 0., 0., + -4., -4., -4., -4., 0., 0., 0., 0., + -24., -24., 20., 20.], + +} + +attr_list_desc = '<timeStamp>run-lumi</timeStamp><addrHeader><address_header service_type="71" clid="40774348" /></addrHeader><typeName>AthenaAttributeList</typeName>' + +cond_attr_list_desc = '<timeStamp>run-lumi</timeStamp><addrHeader><address_header clid="1238547719" service_type="71" /></addrHeader><typeName>CondAttrListCollection</typeName>' + +maxInt32 = 0xFFFFFFFF + +# Look for data entry errors + +print('Validating offset data') +lastRun = -1 +for run, data in offset_data.items(): + assert isinstance(run, int), 'Run number is not integer' + assert run > lastRun, 'Run numbers out of order' + assert run <= maxInt32, 'Run number out of range' + lastRun = run + #assert len(data) == offset_channels, 'Offset data does not have '+str(offset_channels)+' entries' + for i in range(len(data)): + assert isinstance(data[i], float), 'Offset time is not float' + +# Data looks OK + +from PyCool import cool +from CoolConvUtilities.AtlCoolLib import indirectOpen + +dbSvc = cool.DatabaseSvcFactory.databaseService() +connectString = f'sqlite://;schema={filename};dbname=CONDBR3' + +print('Opening database') + +# Try to open existing, but if not create new +try: + db = indirectOpen(connectString, readOnly=False) +except Exception as e: + print(e) + print("Couldn't open, try creating new") + #dbSvc.dropDatabase( connectString ) + db = dbSvc.createDatabase( connectString ) + +# Trigger offset times + +offsetSpec = cool.RecordSpecification() +offsetSpec.extend( 'TriggerOffset', cool.StorageType.Float ) + +offsetFolderSpec = cool.FolderSpecification(cool.FolderVersioning.SINGLE_VERSION, offsetSpec) +offsetFolder = db.createFolder('/WAVE/DAQ/TimingOffset', offsetFolderSpec, cond_attr_list_desc, True) + +# There should be one record entered per IOV +lastValid = cool.ValidityKeyMax +for firstValidRun, offset_list in reversed(offset_data.items()): + firstValid = (firstValidRun << 32) + for channel in range(len(offset_list)): + offsetRecord = cool.Record(offsetSpec) + offsetRecord[ 'TriggerOffset' ] = float(offset_list[channel]) + offsetFolder.storeObject( firstValid, lastValid, offsetRecord, cool.ChannelId(channel) ) + + lastValid = ((firstValidRun - 1) << 32) | (cool.ValidityKeyMax & 0x00000000FFFFFFFF) + + +db.closeDatabase() + +print('Database completed') + +print('Working on MC database') + +# No offsets by default +# Expand this to 20 channels for 2024 data +offset_data = { + 0: [0., 0., 0., 0., 0., 0., 0., 0., + 0., 0., 0., 0., 0., 0., 0., 0., + 0., 0., 0., 0.] +} + +# Validate again just in case + +print('Validating offset data') +lastRun = -1 +for run, data in offset_data.items(): + assert isinstance(run, int), 'Run number is not integer' + assert run > lastRun, 'Run numbers out of order' + assert run <= maxInt32, 'Run number out of range' + lastRun = run + #assert len(data) == offset_channels, 'Offset data does not have '+str(offset_channels)+' entries' + for i in range(len(data)): + assert isinstance(data[i], float), 'Offset time is not float' + +# Data looks OK + +connectString = f'sqlite://;schema={filename};dbname=OFLP200' + +print('Opening database') + +# Try to open existing, but if not create new +try: + db = indirectOpen(connectString, readOnly=False) +except Exception as e: + print(e) + print("Couldn't open, try creating new") + #dbSvc.dropDatabase( connectString ) + db = dbSvc.createDatabase( connectString ) + +# Trigger offset times + +offsetSpec = cool.RecordSpecification() +offsetSpec.extend( 'TriggerOffset', cool.StorageType.Float ) + +offsetFolderSpec = cool.FolderSpecification(cool.FolderVersioning.SINGLE_VERSION, offsetSpec) +offsetFolder = db.createFolder('/WAVE/DAQ/TimingOffset', offsetFolderSpec, cond_attr_list_desc, True) + +# There should be one record entered per IOV +lastValid = cool.ValidityKeyMax +for firstValidRun, offset_list in reversed(offset_data.items()): + firstValid = (firstValidRun << 32) + for channel in range(len(offset_list)): + offsetRecord = cool.Record(offsetSpec) + offsetRecord[ 'TriggerOffset' ] = float(offset_list[channel]) + offsetFolder.storeObject( firstValid, lastValid, offsetRecord, cool.ChannelId(channel) ) + + lastValid = ((firstValidRun - 1) << 32) | (cool.ValidityKeyMax & 0x00000000FFFFFFFF) + + +db.closeDatabase() + +print('Database completed') diff --git a/Waveform/WaveformConditions/WaveformConditionsTools/src/WaveformCableMappingTool.cxx b/Waveform/WaveformConditions/WaveformConditionsTools/src/WaveformCableMappingTool.cxx index 8771650cf2d39b947ccaffcee901020331f1d59b..9fc8c75d4853f5d9acc46af5374eb0815400acaa 100644 --- a/Waveform/WaveformConditions/WaveformConditionsTools/src/WaveformCableMappingTool.cxx +++ b/Waveform/WaveformConditions/WaveformConditionsTools/src/WaveformCableMappingTool.cxx @@ -26,10 +26,12 @@ WaveformCableMappingTool::initialize() { // Set up helpers ATH_CHECK(detStore()->retrieve(m_ecalID, "EcalID")); + ATH_CHECK(detStore()->retrieve(m_caloNuID, "CaloNuID")); ATH_CHECK(detStore()->retrieve(m_vetoID, "VetoID")); ATH_CHECK(detStore()->retrieve(m_vetoNuID, "VetoNuID")); ATH_CHECK(detStore()->retrieve(m_triggerID, "TriggerID")); ATH_CHECK(detStore()->retrieve(m_preshowerID, "PreshowerID")); + ATH_CHECK(detStore()->retrieve(m_muonID, "MuonID")); return StatusCode::SUCCESS; } @@ -97,21 +99,21 @@ WaveformCableMappingTool::getCableMapping(const EventContext& ctx) const { // Do checks of PMT identifier identifier = m_ecalID->pmt_id(rowVal, moduleVal, pmtVal, true); // Test a few things - ATH_MSG_DEBUG("Calo ID:" << identifier); + ATH_MSG_DEBUG("Calo ID:" << identifier); ATH_MSG_DEBUG("PMT:" << m_ecalID->pmt(identifier) << " PMT Max:" << m_ecalID->pmt_max(identifier)); } else if (det_type == "calo2") { // Do checks of PMT identifier identifier = m_ecalID->pmt_id(rowVal, moduleVal, pmtVal, true); - ATH_MSG_DEBUG("Calo2 ID:" << identifier); + ATH_MSG_DEBUG("Calo2 ID:" << identifier); ATH_MSG_DEBUG("PMT:" << m_ecalID->pmt(identifier) << " PMT Max:" << m_ecalID->pmt_max(identifier)); } - else if (det_type == "calo2") { + else if (det_type == "calonu") { // Do checks of PMT identifier - identifier = m_ecalID->pmt_id(rowVal, moduleVal, pmtVal, true); - ATH_MSG_DEBUG("Calo2 ID:" << identifier); - ATH_MSG_DEBUG("PMT:" << m_ecalID->pmt(identifier) << " PMT Max:" << m_ecalID->pmt_max(identifier)); - } + identifier = m_caloNuID->pmt_id(rowVal, moduleVal, pmtVal, true); + ATH_MSG_DEBUG("CaloNu ID:" << identifier); + ATH_MSG_DEBUG("PMT:" << m_caloNuID->pmt(identifier) << " PMT Max:" << m_caloNuID->pmt_max(identifier)); + } else if (det_type == "veto") { identifier = m_vetoID->pmt_id(stationVal, plateVal, pmtVal); } @@ -124,6 +126,9 @@ WaveformCableMappingTool::getCableMapping(const EventContext& ctx) const { else if (det_type == "preshower") { identifier = m_preshowerID->pmt_id(stationVal, plateVal, pmtVal); } + else if (det_type == "muon") { + identifier = m_muonID->pmt_id(stationVal, plateVal, pmtVal); + } else if (det_type == "clock") { // No valid identifiers for these identifier = -1; @@ -205,6 +210,9 @@ WaveformCableMappingTool::getChannelMapping(const EventContext& ctx, const Ident else if (det_type == "calo2") { identifier = m_ecalID->pmt_id(rowVal, moduleVal, pmtVal); } + else if (det_type == "calonu") { + identifier = m_caloNuID->pmt_id(rowVal, moduleVal, pmtVal); + } else if (det_type == "veto") { identifier = m_vetoID->pmt_id(stationVal, plateVal, pmtVal); } @@ -217,6 +225,9 @@ WaveformCableMappingTool::getChannelMapping(const EventContext& ctx, const Ident else if (det_type == "preshower") { identifier = m_preshowerID->pmt_id(stationVal, plateVal, pmtVal); } + else if (det_type == "muon") { + identifier = m_muonID->pmt_id(stationVal, plateVal, pmtVal); + } else if (det_type == "clock") { // No valid identifiers for these identifier = -1; diff --git a/Waveform/WaveformConditions/WaveformConditionsTools/src/WaveformCableMappingTool.h b/Waveform/WaveformConditions/WaveformConditionsTools/src/WaveformCableMappingTool.h index 8443cb1815e4db7a9c0181515b5fd405cd27d48c..0d458314374fb293312f1cce4dcc5e4acb4ddf74 100644 --- a/Waveform/WaveformConditions/WaveformConditionsTools/src/WaveformCableMappingTool.h +++ b/Waveform/WaveformConditions/WaveformConditionsTools/src/WaveformCableMappingTool.h @@ -20,10 +20,12 @@ // Identifiers #include "Identifier/Identifier.h" #include "FaserCaloIdentifier/EcalID.h" +#include "FaserCaloIdentifier/CaloNuID.h" #include "ScintIdentifier/VetoID.h" #include "ScintIdentifier/VetoNuID.h" #include "ScintIdentifier/TriggerID.h" #include "ScintIdentifier/PreshowerID.h" +#include "ScintIdentifier/MuonID.h" // Include Athena stuff #include "AthenaPoolUtilities/CondAttrListCollection.h" @@ -70,10 +72,13 @@ class WaveformCableMappingTool: public extends<AthAlgTool, IWaveformCableMapping // ID helpers const EcalID* m_ecalID{nullptr}; + const CaloNuID* m_caloNuID{nullptr}; + const VetoID* m_vetoID{nullptr}; const VetoNuID* m_vetoNuID{nullptr}; const TriggerID* m_triggerID{nullptr}; const PreshowerID* m_preshowerID{nullptr}; + const MuonID* m_muonID{nullptr}; }; diff --git a/xAOD/xAODFaserWaveform/Root/WaveformClockAuxInfo_v1.cxx b/xAOD/xAODFaserWaveform/Root/WaveformClockAuxInfo_v1.cxx index 61d5dc8e8d736c44ceba480964551bed85ccf981..87234028f27533873de487fba72439d09b634090 100644 --- a/xAOD/xAODFaserWaveform/Root/WaveformClockAuxInfo_v1.cxx +++ b/xAOD/xAODFaserWaveform/Root/WaveformClockAuxInfo_v1.cxx @@ -9,10 +9,11 @@ namespace xAOD { WaveformClockAuxInfo_v1::WaveformClockAuxInfo_v1() : AuxInfoBase(), - frequency(0), phase(0), dc_offset(0), amplitude(0) { + frequency(0), phase(0), dc_offset(0), amplitude(0), time_offset(0) { AUX_VARIABLE( frequency ); AUX_VARIABLE( phase ); AUX_VARIABLE( dc_offset ); AUX_VARIABLE( amplitude ); + AUX_VARIABLE( time_offset ); } } // namespace xAOD diff --git a/xAOD/xAODFaserWaveform/Root/WaveformClock_v1.cxx b/xAOD/xAODFaserWaveform/Root/WaveformClock_v1.cxx index 04498ccc8ecfc6e0a2c62d1c404318988229b891..c05d5cdc1cf18fd6389a62a25d0fa6a2086f301e 100644 --- a/xAOD/xAODFaserWaveform/Root/WaveformClock_v1.cxx +++ b/xAOD/xAODFaserWaveform/Root/WaveformClock_v1.cxx @@ -21,12 +21,19 @@ namespace xAOD { AUXSTORE_PRIMITIVE_SETTER_AND_GETTER( WaveformClock_v1, double, amplitude, set_amplitude ) + AUXSTORE_PRIMITIVE_SETTER_AND_GETTER( WaveformClock_v1, double, time_offset, set_time_offset ) + float WaveformClock_v1::time_from_clock(float time) const { // Figure out which integer cycle we are on, must add 1/4 of a cycle // because FFT finds phase of cosine, which would be middle of // clock HI region. frequency is in MHz, so convert here to GHz - int ncycle = int(time*frequency() / 1.E3 + phase() / (2*M_PI) + 0.25); - float dt = time - (ncycle - phase() / (2*M_PI) - 0.25) * 1.E3 / frequency(); + + // Because the clock is in digitizer 2, it may be early + // Adjust the time to take this into account + // These times should also be corrected if they are shifted + int ncycle = int((time+time_offset())*frequency() / 1.E3 + phase() / (2*M_PI) + 0.25); + float dt = (time + time_offset()) - (ncycle - phase() / (2*M_PI) - 0.25) * 1.E3 / frequency(); + // Also apply return dt; } @@ -39,6 +46,7 @@ namespace xAOD { << " phase=" << clk.phase() << " amplitude=" << clk.amplitude() << " offset=" << clk.dc_offset() + << " time_offset=" << clk.time_offset() << std::endl; return s; diff --git a/xAOD/xAODFaserWaveform/xAODFaserWaveform/versions/WaveformClockAuxInfo_v1.h b/xAOD/xAODFaserWaveform/xAODFaserWaveform/versions/WaveformClockAuxInfo_v1.h index 24741e2476ab952f316a8ceeaf7611361bdd291d..75b462829678451213c92c9cc2e2328497bc885c 100644 --- a/xAOD/xAODFaserWaveform/xAODFaserWaveform/versions/WaveformClockAuxInfo_v1.h +++ b/xAOD/xAODFaserWaveform/xAODFaserWaveform/versions/WaveformClockAuxInfo_v1.h @@ -32,6 +32,7 @@ namespace xAOD { double phase; double dc_offset; double amplitude; + double time_offset; ///@} }; // class WaveformClockAuxInfo_v1 diff --git a/xAOD/xAODFaserWaveform/xAODFaserWaveform/versions/WaveformClock_v1.h b/xAOD/xAODFaserWaveform/xAODFaserWaveform/versions/WaveformClock_v1.h index 437b3ecabf1f71c9be0c353d27bebec1d0916d11..cc1fbc858d7e2ddb28dee4430ad2d7f23026c6b4 100644 --- a/xAOD/xAODFaserWaveform/xAODFaserWaveform/versions/WaveformClock_v1.h +++ b/xAOD/xAODFaserWaveform/xAODFaserWaveform/versions/WaveformClock_v1.h @@ -43,6 +43,10 @@ namespace xAOD { double amplitude() const; void set_amplitude(double value); + /// Possible time shift due to 2nd digitizer trigger + double time_offset() const; + void set_time_offset(double value); + /// Distance of time (in ns) from previous rising clock edge float time_from_clock(float time) const; diff --git a/xAOD/xAODFaserWaveform/xAODFaserWaveform/versions/WaveformHit_v1.h b/xAOD/xAODFaserWaveform/xAODFaserWaveform/versions/WaveformHit_v1.h index 4f15e8152fa7ea2d00ae6eed970d9341ffc6fba4..33fccbc3c224f5e3de4bd47b859805062c5f17a3 100644 --- a/xAOD/xAODFaserWaveform/xAODFaserWaveform/versions/WaveformHit_v1.h +++ b/xAOD/xAODFaserWaveform/xAODFaserWaveform/versions/WaveformHit_v1.h @@ -30,7 +30,8 @@ namespace xAOD { CBFIT_FAILED, // CrystalBall fit failed CLOCK_INVALID, WAVEFORM_MISSING, // Input waveform data missing - WAVEFORM_INVALID // Input waveform data length mismatch + WAVEFORM_INVALID, // Input waveform data length mismatch + TIMING_SHIFTED // Time of digitizer 2 hits shifted for trigger }; // Cllss describing pulses in the waveform digitizer