diff --git a/Calorimeter/CaloRecAlgs/CMakeLists.txt b/Calorimeter/CaloRecAlgs/CMakeLists.txt index 219db92a3a8927ae9cc025bea46985387e072ce0..75d9d09a23eb857555e55848ee16b1d2b98b89f3 100644 --- a/Calorimeter/CaloRecAlgs/CMakeLists.txt +++ b/Calorimeter/CaloRecAlgs/CMakeLists.txt @@ -9,7 +9,7 @@ atlas_subdir( CaloRecAlgs ) atlas_add_component( CaloRecAlgs src/*.cxx src/*.h src/components/*.cxx - LINK_LIBRARIES AthenaBaseComps StoreGateLib xAODFaserCalorimeter xAODFaserWaveform) + LINK_LIBRARIES AthenaKernel GaudiKernel AthenaBaseComps AthenaPoolUtilities StoreGateLib xAODFaserCalorimeter xAODFaserWaveform CaloRecToolsLib) atlas_install_python_modules( python/*.py ) diff --git a/Calorimeter/CaloRecAlgs/python/CaloRecAlgsConfig.py b/Calorimeter/CaloRecAlgs/python/CaloRecAlgsConfig.py index 034bf08b5b36a4620567f6716eca5d31338a1c04..83839b9cba1a4c6a50eef52852ed8ee2127dfaa7 100644 --- a/Calorimeter/CaloRecAlgs/python/CaloRecAlgsConfig.py +++ b/Calorimeter/CaloRecAlgs/python/CaloRecAlgsConfig.py @@ -1,30 +1,31 @@ -""" Define methods used to instantiate configured Waveform reconstruction tools and algorithms +""" Define methods used to instantiate configured Calorimeter Calibration reconstruction tools and algorithms -Copyright (C) 2020 CERN for the benefit of the FASER collaboration +Copyright (C) 2022 CERN for the benefit of the FASER collaboration """ from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator from AthenaConfiguration.ComponentFactory import CompFactory - +from IOVDbSvc.IOVDbSvcConfig import addFolders from OutputStreamAthenaPool.OutputStreamConfig import OutputStreamCfg -#CalorimeterReconstructionTool = CompFactory.CalorimeterReconstructionTool +from CaloRecTools.CaloRecToolConfig import CaloRecToolCfg # One stop shopping for normal FASER data def CalorimeterReconstructionCfg(flags, **kwargs): """ Return all algorithms and tools for Waveform reconstruction """ acc = ComponentAccumulator() - #tool = CalorimeterReconstructionTool(name="CaloRecTool", **kwargs) - kwargs.setdefault("CaloWaveHitContainerKey", "CaloWaveformHits") kwargs.setdefault("PreshowerWaveHitContainerKey", "PreshowerWaveformHits") kwargs.setdefault("CaloHitContainerKey", "CaloHits") - #kwargs.setdefault("CalorimeterReconstructionTool", tool) + kwargs.setdefault("PreshowerHitContainerKey", "PreshowerHits") recoAlg = CompFactory.CaloRecAlg("CaloRecAlg", **kwargs) - #recoAlg.CalorimeterReconstructionTool = tool acc.addEventAlgo(recoAlg) + dbInstance = kwargs.get("dbInstance", "TRIGGER_OFL") # what should this be set to??? + + acc.merge(CaloRecToolCfg(flags)) + return acc def CalorimeterReconstructionOutputCfg(flags, **kwargs): diff --git a/Calorimeter/CaloRecAlgs/src/CaloRecAlg.cxx b/Calorimeter/CaloRecAlgs/src/CaloRecAlg.cxx index 4b4d6f158f29478a60443381c5292d254d1c665f..f4f78d488d6c542637003e38ea0d8959f89b6b1c 100644 --- a/Calorimeter/CaloRecAlgs/src/CaloRecAlg.cxx +++ b/Calorimeter/CaloRecAlgs/src/CaloRecAlg.cxx @@ -1,4 +1,5 @@ #include "CaloRecAlg.h" +#include <math.h> CaloRecAlg::CaloRecAlg(const std::string& name, ISvcLocator* pSvcLocator) @@ -6,13 +7,9 @@ CaloRecAlg::CaloRecAlg(const std::string& name, } -StatusCode -CaloRecAlg::initialize() { +StatusCode CaloRecAlg::initialize() { ATH_MSG_INFO(name() << "::initalize()" ); - // Initalize tools - //ATH_CHECK( m_recoTool.retrieve() ); - // Set key to read calo hits from ATH_CHECK( m_caloWaveHitContainerKey.initialize() ); @@ -21,19 +18,27 @@ CaloRecAlg::initialize() { // Set key to write container ATH_CHECK( m_caloHitContainerKey.initialize() ); + ATH_CHECK( m_preshowerHitContainerKey.initialize() ); + + // Initalize tools + ATH_CHECK( m_recoCalibTool.retrieve() ); + + // Store calibrattiion factos in a vector for ease of access + m_EM_mu_Map[0] = m_calo_ch0_EM_mu; + m_EM_mu_Map[1] = m_calo_ch1_EM_mu; + m_EM_mu_Map[2] = m_calo_ch2_EM_mu; + m_EM_mu_Map[3] = m_calo_ch3_EM_mu; return StatusCode::SUCCESS; } - -StatusCode -CaloRecAlg::finalize() { +//---------------------------------------------------------------------- +StatusCode CaloRecAlg::finalize() { ATH_MSG_INFO(name() << "::finalize()"); return StatusCode::SUCCESS; } - -StatusCode -CaloRecAlg::execute(const EventContext& ctx) const { +//---------------------------------------------------------------------- +StatusCode CaloRecAlg::execute(const EventContext& ctx) const { ATH_MSG_DEBUG("Executing"); ATH_MSG_DEBUG("Run: " << ctx.eventID().run_number() @@ -63,61 +68,112 @@ CaloRecAlg::execute(const EventContext& ctx) const { ATH_CHECK( caloHitContainerHandle.record( std::make_unique<xAOD::CalorimeterHitContainer>(), std::make_unique<xAOD::CalorimeterHitAuxContainer>() ) ); + SG::WriteHandle<xAOD::CalorimeterHitContainer> preshowerHitContainerHandle(m_preshowerHitContainerKey, ctx); + ATH_CHECK( preshowerHitContainerHandle.record( std::make_unique<xAOD::CalorimeterHitContainer>(), + std::make_unique<xAOD::CalorimeterHitAuxContainer>() ) ); + ATH_MSG_DEBUG("WaveformsHitContainer '" << caloHitContainerHandle.name() << "' initialized"); + ATH_MSG_DEBUG("WaveformsHitContainer '" << preshowerHitContainerHandle.name() << "' initialized"); + + // Loop over calo hits and calibrate each primary hit + for( const auto& hit : *caloWaveHitHandle ) { + if (hit->status_bit(xAOD::WaveformStatus::SECONDARY)) continue; + + // Create a new calo hit + xAOD::CalorimeterHit* calo_hit = new xAOD::CalorimeterHit(); + caloHitContainerHandle->push_back(calo_hit); - // Reconstruct all waveforms - //CHECK( m_recoTool->reconstructAll(*waveformHandle, clockptr, hitContainerHandle.ptr()) ); - - // Find peak time (most significant hit) - const xAOD::WaveformHit* peakHit = findPeakHit(*caloWaveHitHandle); - if (peakHit == NULL) return StatusCode::SUCCESS; - - // Create a new calo hit - xAOD::CalorimeterHit* calo_hit = new xAOD::CalorimeterHit(); - caloHitContainerHandle->push_back(calo_hit); - - calo_hit->set_raw_energy(-1.); // Dummy value - - // Find closest hits in time per channel - std::map<int, const xAOD::WaveformHit*> hitMap; - for ( const auto& hit : *caloWaveHitHandle ) { - int channel = hit->channel(); - if (hitMap.count(channel) == 0) - hitMap[channel] = hit; - else { - if (abs(hitMap[channel]->localtime() - peakHit->localtime()) > - abs(hit->localtime() - peakHit->localtime())) - hitMap[channel] = hit; + ATH_MSG_DEBUG("calo_hit in channel " << hit->channel() ); + + float MIPcharge_ref = m_recoCalibTool->getMIPcharge_ref(hit->channel()); // get reference MIP charge from database + + float charge = hit->integral()/50.0; // divide by 50 ohms to get charge + ATH_MSG_DEBUG("calo_hit filled has charge of " << charge << " pC"); + + float gainRatio = 1.0; + if (m_isMC) { + gainRatio = 1.0; // put dummy value for now, this will end up being ratio of digi scale factors + } else { + gainRatio = extrapolateHVgain(hit->channel()); + ATH_MSG_DEBUG("HV gain ratio = " << gainRatio ); } - } - // For each hit found, insert these into the caloHit - // Clear before association - calo_hit->clearCaloWaveformLinks(); - for ( const auto& [chan, hit] : hitMap ) { - ATH_MSG_VERBOSE("Found hit " << *hit); - calo_hit->addCaloHit(caloWaveHitHandle.get(), hit); + float Nmip = (charge * gainRatio) / MIPcharge_ref; + ATH_MSG_DEBUG("Nmip = " << Nmip ); + calo_hit->set_Nmip(Nmip); // set Nmip value + + float E_dep = Nmip * m_MIP_sim_Edep_calo; + ATH_MSG_DEBUG("E_dep in MeV = " << E_dep ); + calo_hit->set_E_dep(E_dep); // set calibrated E_dep value + + float E_EM = Nmip * m_EM_mu_Map[hit->channel()]; + ATH_MSG_DEBUG("Em E in MeV = " << E_EM ); + calo_hit->set_E_EM(E_EM); // set calibrated E_EM value + + float fit_to_raw_ratio = 1.0; + if (hit->integral() != 0.0) { // avoid possibility of division by zero error + fit_to_raw_ratio = hit->raw_integral() / hit->integral(); + } + calo_hit->set_fit_to_raw_ratio(fit_to_raw_ratio); // set fit-to-raw-ratio that can be used to take any of the calibrated values to what they would be if we used the raw integral instead of the fit integral + + calo_hit->set_channel(hit->channel()); // set channel number + + calo_hit->clearWaveformLinks(); + calo_hit->addHit(caloWaveHitHandle.get(), hit); // create link to calo waveform hit } ATH_MSG_DEBUG("CaloHitContainer '" << caloHitContainerHandle.name() << "' filled with "<< caloHitContainerHandle->size() <<" items"); - return StatusCode::SUCCESS; -} + for( const auto& hit : *preshowerWaveHitHandle ) { + if (hit->status_bit(xAOD::WaveformStatus::SECONDARY)) continue; -const xAOD::WaveformHit* -CaloRecAlg::findPeakHit(const xAOD::WaveformHitContainer& hitContainer) const { + // Create a new preshower hit + xAOD::CalorimeterHit* preshower_hit = new xAOD::CalorimeterHit(); + preshowerHitContainerHandle->push_back(preshower_hit); - const xAOD::WaveformHit* peakHit = NULL; - for( const auto& hit : hitContainer ) { - if (peakHit == NULL) { - peakHit = hit; - } else { - if ( hit->peak() > peakHit->peak() ) peakHit = hit; + ATH_MSG_DEBUG("preshower_hit in channel " << hit->channel() ); + + float MIPcharge_ref = m_recoCalibTool->getMIPcharge_ref(hit->channel()); // get reference MIP charge from database + + float charge = hit->integral()/50.0; // divide by 50 ohms to get charge + ATH_MSG_DEBUG("preshower_hit filled has charge of " << charge << " pC"); + + float Nmip = charge / MIPcharge_ref; + ATH_MSG_DEBUG("Nmip = " << Nmip ); + preshower_hit->set_Nmip(Nmip); // set Nmip value + + float E_dep = Nmip * m_MIP_sim_Edep_preshower; + ATH_MSG_DEBUG("E_dep in GeV = " << E_dep ); + preshower_hit->set_E_dep(E_dep); // set calibrated E_dep value + + float fit_to_raw_ratio = 1.0; + if (hit->integral() != 0.0) { // avoid possibility of division by zero error + fit_to_raw_ratio = hit->raw_integral() / hit->integral(); } + preshower_hit->set_fit_to_raw_ratio(fit_to_raw_ratio); // set fit-to-raw-ratio that can be used to take any of the calibrated values to what they would be if we used the raw integral instead of the fit integral + + preshower_hit->set_channel(hit->channel()); // set channel number + + preshower_hit->clearWaveformLinks(); + preshower_hit->addHit(preshowerWaveHitHandle.get(), hit); // create link to preshower waveform hit } - // Didn't find anything? - if (peakHit == NULL) return NULL; - if (peakHit->status_bit(xAOD::WaveformStatus::THRESHOLD_FAILED)) return NULL; - return peakHit; + ATH_MSG_DEBUG("PreshowerHitContainer '" << preshowerHitContainerHandle.name() << "' filled with "<< preshowerHitContainerHandle->size() <<" items"); + + + return StatusCode::SUCCESS; } + +//---------------------------------------------------------------------- +float CaloRecAlg::extrapolateHVgain(int channel) const { + float PMT_hv = m_recoCalibTool->getHV(channel); + float PMT_hv_ref = m_recoCalibTool->getHV_ref(channel); + TF1 gaincurve = m_recoCalibTool->get_PMT_HV_curve(channel); + + float gaincurve_atHV = gaincurve.Eval(PMT_hv); + float gaincurve_atHVref = gaincurve.Eval(PMT_hv_ref); + + return ( gaincurve_atHVref / gaincurve_atHV ) * pow( PMT_hv_ref / PMT_hv , 6.6); +} +//---------------------------------------------------------------------- + diff --git a/Calorimeter/CaloRecAlgs/src/CaloRecAlg.h b/Calorimeter/CaloRecAlgs/src/CaloRecAlg.h index bd98e9afd6b693b8cc4518ebd87ddd72207fddef..721f521621ae519778a8ddadd8b5711f1beeac9b 100644 --- a/Calorimeter/CaloRecAlgs/src/CaloRecAlg.h +++ b/Calorimeter/CaloRecAlgs/src/CaloRecAlg.h @@ -12,7 +12,11 @@ #include "xAODFaserCalorimeter/CalorimeterHitAuxContainer.h" // Tool classes -//#include "CaloRecTools/ICalorimeterReconstructionTool.h" +#include "CaloRecTools/ICaloRecTool.h" + +// Include Athena stuff for Conditions db reading +#include "AthenaPoolUtilities/CondAttrListCollection.h" +#include "StoreGate/ReadCondHandleKey.h" // Handles #include "StoreGate/ReadHandleKey.h" @@ -21,9 +25,16 @@ // Gaudi #include "GaudiKernel/ServiceHandle.h" #include "GaudiKernel/ToolHandle.h" +#include "GaudiKernel/EventContext.h" +#include "GaudiKernel/ICondSvc.h" +#include "Gaudi/Property.h" + +// ROOT +#include "TF1.h" // STL #include <string> +#include <vector> class CaloRecAlg : public AthReentrantAlgorithm { @@ -51,32 +62,40 @@ class CaloRecAlg : public AthReentrantAlgorithm { /** * @name Reconstruction tool */ - //ToolHandle<ICalorimeterReconstructionTool> m_recoTool - //{this, "CalorimeterReconstructionTool", "CalorimeterReconstructionTool"}; + ToolHandle<ICaloRecTool> m_recoCalibTool {this, "CaloRecTool", "CaloRecTool"}; /** * @name Input raw waveform data using SG::ReadHandleKey */ //@{ - SG::ReadHandleKey<xAOD::WaveformHitContainer> m_caloWaveHitContainerKey - {this, "CaloWaveHitContainerKey", ""}; + SG::ReadHandleKey<xAOD::WaveformHitContainer> m_caloWaveHitContainerKey {this, "CaloWaveHitContainerKey", "CaloWaveformHits"}; //@} //@{ - SG::ReadHandleKey<xAOD::WaveformHitContainer> m_preshowerWaveHitContainerKey - {this, "PreshowerWaveHitContainerKey", ""}; + SG::ReadHandleKey<xAOD::WaveformHitContainer> m_preshowerWaveHitContainerKey {this, "PreshowerWaveHitContainerKey", "PreshowerWaveformHits"}; //@} /** * @name Output data using SG::WriteHandleKey */ //@{ - SG::WriteHandleKey<xAOD::CalorimeterHitContainer> m_caloHitContainerKey - {this, "CaloHitContainerKey", ""}; + SG::WriteHandleKey<xAOD::CalorimeterHitContainer> m_caloHitContainerKey {this, "CaloHitContainerKey", "CaloHits"}; + SG::WriteHandleKey<xAOD::CalorimeterHitContainer> m_preshowerHitContainerKey {this, "PreshowerHitContainerKey", "PreshowerHits"}; //@} - const xAOD::WaveformHit* - findPeakHit(const xAOD::WaveformHitContainer& hitContainer) const; + float extrapolateHVgain(int channel) const; + + 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_preshower {this, "MIP_sim_Edep_preshower", 4.894}; // MIP deposits 4.894 MeV of energy in a preshower layer + + FloatProperty m_calo_ch0_EM_mu {this, "m_calo_ch0_EM_mu", 330.0}; // factor used to do rough calibration of calo ch0 to EM energy: 0.33 GeV or 330 MeV + FloatProperty m_calo_ch1_EM_mu {this, "m_calo_ch1_EM_mu", 330.0}; // factor used to do rough calibration of calo ch1 to EM energy: 0.33 GeV or 330 MeV + FloatProperty m_calo_ch2_EM_mu {this, "m_calo_ch2_EM_mu", 330.0}; // factor used to do rough calibration of calo ch2 to EM energy: 0.33 GeV or 330 MeV + FloatProperty m_calo_ch3_EM_mu {this, "m_calo_ch3_EM_mu", 330.0}; // factor used to do rough calibration of calo ch3 to EM energy: 0.33 GeV or 330 MeV + + float m_EM_mu_Map[4]; // vector that holds EM_mu calibration factors for calo channels + + Gaudi::Property<bool> m_isMC {this, "isMC", false}; }; diff --git a/Calorimeter/CaloRecTools/CMakeLists.txt b/Calorimeter/CaloRecTools/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..f0e9f07b53f5426b360c2639d4f7953a44d57792 --- /dev/null +++ b/Calorimeter/CaloRecTools/CMakeLists.txt @@ -0,0 +1,30 @@ +################################################################################ +# Package: CaloRecTools +################################################################################ + +# Declare the package name: +atlas_subdir( CaloRecTools ) + +# External dependencies: +find_package( ROOT ) + +# Component(s) in the package: +atlas_add_library( CaloRecToolsLib + CaloRecTools/*.h src/*.cxx src/*.h + PUBLIC_HEADERS CaloRecTools + PRIVATE_INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} + LINK_LIBRARIES AthenaBaseComps AthenaPoolUtilities AthenaKernel GaudiKernel + PRIVATE_LINK_LIBRARIES ${ROOT_LIBRARIES} + ) + +atlas_add_component( CaloRecTools + src/components/*.cxx + INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} + LINK_LIBRARIES ${ROOT_LIBRARIES} + AthenaBaseComps AthenaPoolUtilities AthenaKernel GaudiKernel + CaloRecToolsLib) + +# Install files from the package: +atlas_install_python_modules( python/*.py ) + + diff --git a/Calorimeter/CaloRecTools/CaloRecTools/ICaloRecTool.h b/Calorimeter/CaloRecTools/CaloRecTools/ICaloRecTool.h new file mode 100644 index 0000000000000000000000000000000000000000..feb141d915d6214a681f437d94b8118e14c33820 --- /dev/null +++ b/Calorimeter/CaloRecTools/CaloRecTools/ICaloRecTool.h @@ -0,0 +1,45 @@ +/* + Copyright (C) 2022 CERN for the benefit of the FASER collaboration +*/ + +/** + * @file ICaloRecTool.h + * Header file for the ICaloRecTool class + * @author Deion Fellers, 2022 + */ + + +#ifndef CALORECTOOL_ICALORECTOOL_H +#define CALORECTOOL_ICALORECTOOL_H + +// Base class +#include "GaudiKernel/IAlgTool.h" +#include "GaudiKernel/ToolHandle.h" +#include "GaudiKernel/EventContext.h" + +#include "TF1.h" + +///Interface for Calo reco algorithms +class ICaloRecTool : virtual public IAlgTool +{ + public: + + // InterfaceID + DeclareInterfaceID(ICaloRecTool, 1, 0); + + virtual ~ICaloRecTool() = default; //!< Destructor + + // methods to return calibration database data + virtual float getHV(const EventContext& ctx, int channel) const = 0; + virtual float getHV(int channel) const = 0; + + virtual float getHV_ref(const EventContext& ctx, int channel) const = 0; + virtual float getHV_ref(int channel) const = 0; + + virtual float getMIPcharge_ref(const EventContext& ctx, int channel) const = 0; + virtual float getMIPcharge_ref(int channel) const = 0; + + virtual TF1 get_PMT_HV_curve(int channel) const = 0; +}; + +#endif // CALORECTOOL_ICALORECTOOL_H diff --git a/Calorimeter/CaloRecTools/python/CaloRecToolConfig.py b/Calorimeter/CaloRecTools/python/CaloRecToolConfig.py new file mode 100644 index 0000000000000000000000000000000000000000..65be875da12b6deee3cbf9f35217cee6f40784ff --- /dev/null +++ b/Calorimeter/CaloRecTools/python/CaloRecToolConfig.py @@ -0,0 +1,27 @@ +""" Define methods to configure CaloRecTool + +Copyright (C) 2022 CERN for the benefit of the FASER collaboration +""" +from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator +from AthenaConfiguration.ComponentFactory import CompFactory +from IOVDbSvc.IOVDbSvcConfig import addFolders +CaloRecTool=CompFactory.CaloRecTool + + +def CaloRecToolCfg(flags, name="CaloRecTool", **kwargs): + """ Return configured ComponentAccumulator and tool for Calo Calibration + + CaloRecTool may be provided in kwargs + """ + + acc = ComponentAccumulator() + # tool = kwargs.get("CaloRecTool", CaloRecTool(flags)) + # Probably need to figure this out! + dbInstance = kwargs.get("dbInstance", "TRIGGER_OFL") + + acc.merge(addFolders(flags, "/WAVE/Calibration/HV", dbInstance, className="CondAttrListCollection")) + acc.merge(addFolders(flags, "/WAVE/Calibration/MIP_ref", dbInstance, className="CondAttrListCollection")) + + return acc + + diff --git a/Calorimeter/CaloRecTools/src/CaloRecTool.cxx b/Calorimeter/CaloRecTools/src/CaloRecTool.cxx new file mode 100644 index 0000000000000000000000000000000000000000..916011019805ab9087c57427859086dec456eb80 --- /dev/null +++ b/Calorimeter/CaloRecTools/src/CaloRecTool.cxx @@ -0,0 +1,194 @@ +/* + Copyright (C) 2022 CERN for the benefit of the FASER collaboration +*/ + +/** + * @file CaloRecTool.cxx + * Implementation file for the CaloRecTool.cxx + * @ author Deion Fellers, 2022 + **/ + +#include "CaloRecTool.h" + +// Constructor +CaloRecTool::CaloRecTool(const std::string& type, const std::string& name, const IInterface* parent) : + base_class(type, name, parent) +{ +} + +//-------------------------------------------------------------- +StatusCode +CaloRecTool::initialize() { + ATH_MSG_INFO( name() << "::initalize()" ); + + // Set keys to read calibratiion variables from data base + ATH_CHECK( m_PMT_HV_ReadKey.initialize() ); + ATH_CHECK( m_MIP_ref_ReadKey.initialize() ); + + // access and store calo PMT HV gain curves + HVgaincurves_rootFile = TFile::Open(m_PMT_HV_Gain_Curve_file.value().c_str(),"read"); // open root file that has TF1 gain curves stored + + chan0_HVgaincurve_pntr = HVgaincurves_rootFile->Get<TF1>(m_chan0_HVgaincurve_name.value().c_str()); // make pointers to the gain curves + chan1_HVgaincurve_pntr = HVgaincurves_rootFile->Get<TF1>(m_chan1_HVgaincurve_name.value().c_str()); + chan2_HVgaincurve_pntr = HVgaincurves_rootFile->Get<TF1>(m_chan2_HVgaincurve_name.value().c_str()); + chan3_HVgaincurve_pntr = HVgaincurves_rootFile->Get<TF1>(m_chan3_HVgaincurve_name.value().c_str()); + + m_HVgainCurveMap[0] = *chan0_HVgaincurve_pntr; // store TF1 objects in an array mapped to the calo channel numbers + m_HVgainCurveMap[1] = *chan1_HVgaincurve_pntr; + m_HVgainCurveMap[2] = *chan2_HVgaincurve_pntr; + m_HVgainCurveMap[3] = *chan3_HVgaincurve_pntr; + + HVgaincurves_rootFile->Close(); // close the root file + + + return StatusCode::SUCCESS; +} + +//-------------------------------------------------------------- +StatusCode +CaloRecTool::finalize() { + // Print where you are + return StatusCode::SUCCESS; +} + +//-------------------------------------------------------------- +TF1 CaloRecTool::get_PMT_HV_curve(int channel) const { + if (channel <= 4) { + return m_HVgainCurveMap[channel]; + } else { + ATH_MSG_WARNING("channel "<<channel<<" is not <= 4 and thus not a calorimeter channel, so no HV gain-curve exists!"); + } + return TF1("default", "1.0", 0.0, 2000.0); +} + +//-------------------------------------------------------------- +float CaloRecTool::getHV(const EventContext& ctx, int channel) const { + + ATH_MSG_DEBUG("in getHV("<<channel<<")"); + + float HV=0.; + + // Read Cond Handle + SG::ReadCondHandle<CondAttrListCollection> readHandle{m_PMT_HV_ReadKey, ctx}; + const CondAttrListCollection* readCdo{*readHandle}; + if (readCdo==nullptr) { + ATH_MSG_FATAL("Null pointer to the read conditions object"); + return HV; + } + // Get the validitiy range + EventIDRange rangeW; + if (not readHandle.range(rangeW)) { + ATH_MSG_FATAL("Failed to retrieve validity range for " << readHandle.key()); + return HV; + } + ATH_MSG_DEBUG("Size of CondAttrListCollection " << readHandle.fullKey() << " readCdo->size()= " << readCdo->size()); + ATH_MSG_DEBUG("Range of input is " << rangeW); + + // Read offset for specific channel + const CondAttrListCollection::AttributeList& payload{readCdo->attributeList(channel)}; + + if (payload.exists("HV") and not payload["HV"].isNull()) { + HV = payload["HV"].data<float>(); + ATH_MSG_DEBUG("Found digitizer channel " << channel << ", HV as " << HV); + } else { + ATH_MSG_WARNING("No valid HV found for channel "<<channel<<"!"); + } + + return HV; + +} + +float CaloRecTool::getHV(int channel) const { + const EventContext& ctx(Gaudi::Hive::currentContext()); + return CaloRecTool::getHV(ctx, channel); +} + +//---------------------------------------------------------------------- +float CaloRecTool::getHV_ref(const EventContext& ctx, int channel) const { + + ATH_MSG_DEBUG("in getHV_ref("<<channel<<")"); + + float HV_ref=0.; + + // Read Cond Handle + SG::ReadCondHandle<CondAttrListCollection> readHandle{m_MIP_ref_ReadKey, ctx}; + const CondAttrListCollection* readCdo{*readHandle}; + if (readCdo==nullptr) { + ATH_MSG_FATAL("Null pointer to the read conditions object"); + return HV_ref; + } + // Get the validitiy range + EventIDRange rangeW; + if (not readHandle.range(rangeW)) { + ATH_MSG_FATAL("Failed to retrieve validity range for " << readHandle.key()); + return HV_ref; + } + ATH_MSG_DEBUG("Size of CondAttrListCollection " << readHandle.fullKey() << " readCdo->size()= " << readCdo->size()); + ATH_MSG_DEBUG("Range of input is " << rangeW); + + // Read offset for specific channel + const CondAttrListCollection::AttributeList& payload{readCdo->attributeList(channel)}; + + if (payload.exists("HV_ref") and not payload["HV_ref"].isNull()) { + HV_ref = payload["HV_ref"].data<float>(); + ATH_MSG_DEBUG("Found digitizer channel " << channel << ", HV_ref as " << HV_ref); + } else { + ATH_MSG_WARNING("No valid HV_ref found for channel "<<channel<<"!"); + } + + return HV_ref; + +} + +float CaloRecTool::getHV_ref(int channel) const { + const EventContext& ctx(Gaudi::Hive::currentContext()); + return CaloRecTool::getHV_ref(ctx, channel); +} + +//---------------------------------------------------------------------- +float CaloRecTool::getMIPcharge_ref(const EventContext& ctx, int channel) const { + + ATH_MSG_DEBUG("in getMIPcharge_ref("<<channel<<")"); + + float MIP_charge_ref =0.; + + // Read Cond Handle + SG::ReadCondHandle<CondAttrListCollection> readHandle{m_MIP_ref_ReadKey, ctx}; + const CondAttrListCollection* readCdo{*readHandle}; + if (readCdo==nullptr) { + ATH_MSG_FATAL("Null pointer to the read conditions object"); + return MIP_charge_ref; + } + // Get the validitiy range + EventIDRange rangeW; + if (not readHandle.range(rangeW)) { + ATH_MSG_FATAL("Failed to retrieve validity range for " << readHandle.key()); + return MIP_charge_ref; + } + ATH_MSG_DEBUG("Size of CondAttrListCollection " << readHandle.fullKey() << " readCdo->size()= " << readCdo->size()); + ATH_MSG_DEBUG("Range of input is " << rangeW); + + // Read offset for specific channel + const CondAttrListCollection::AttributeList& payload{readCdo->attributeList(channel)}; + + if (payload.exists("charge_ref") and not payload["charge_ref"].isNull()) { + MIP_charge_ref = payload["charge_ref"].data<float>(); + ATH_MSG_DEBUG("Found digitizer channel " << channel << ", MIP_charge_ref as " << MIP_charge_ref); + } else { + ATH_MSG_WARNING("No valid MIP_charge_ref found for channel "<<channel<<"!"); + } + + return MIP_charge_ref; + +} + +float CaloRecTool::getMIPcharge_ref(int channel) const { + const EventContext& ctx(Gaudi::Hive::currentContext()); + return CaloRecTool::getMIPcharge_ref(ctx, channel); +} + +//-------------------------------------------------------------- + + + + diff --git a/Calorimeter/CaloRecTools/src/CaloRecTool.h b/Calorimeter/CaloRecTools/src/CaloRecTool.h new file mode 100644 index 0000000000000000000000000000000000000000..6ab891ad42784e3388d933f42de9267545fab3d9 --- /dev/null +++ b/Calorimeter/CaloRecTools/src/CaloRecTool.h @@ -0,0 +1,85 @@ +/* + Copyright (C) 2021 CERN for the benefit of the FASER collaboration +*/ + +/** @file CaloRecTool.h + * Header file for CaloRecTool.h + * + */ +#ifndef CALORECTOOLS_CALORECTOOL_H +#define CALORECTOOLS_CALORECTOOL_H + +// Include interface class +#include "AthenaBaseComps/AthAlgTool.h" +#include "CaloRecTools/ICaloRecTool.h" + +// Include Athena stuff +#include "AthenaPoolUtilities/CondAttrListCollection.h" +#include "StoreGate/ReadCondHandleKey.h" + +#include "GaudiKernel/ICondSvc.h" +#include "Gaudi/Property.h" + +// Include Gaudi classes +#include "GaudiKernel/ICondSvc.h" +#include "Gaudi/Property.h" +#include "GaudiKernel/EventContext.h" + +// Include ROOT classes +#include "TF1.h" +#include "TFile.h" + +#include <string> + +class CaloRecTool: public extends<AthAlgTool, ICaloRecTool> { + public: + + /// Normal constructor for an AlgTool; 'properties' are also declared here + CaloRecTool(const std::string& type, const std::string& name, const IInterface* parent); + + // Standard Gaudi functions + virtual StatusCode initialize() override; //!< Gaudi initialiser + virtual StatusCode finalize() override; //!< Gaudi finaliser + + // methods for returning calibration data + // Channels indexed by digitizer channel number + // HV is in Volts and MIPcharge is in pC + // + virtual float getHV(const EventContext& ctx, int channel) const override; + virtual float getHV(int channel) const override; + + virtual float getHV_ref(const EventContext& ctx, int channel) const override; + virtual float getHV_ref(int channel) const override; + + virtual float getMIPcharge_ref(const EventContext& ctx, int channel) const override; + virtual float getMIPcharge_ref(int channel) const override; + + // method for returning PMT HV calibration curves from root file + virtual TF1 get_PMT_HV_curve(int channel) const override; + + TFile* HVgaincurves_rootFile; + + TF1* chan0_HVgaincurve_pntr; + TF1* chan1_HVgaincurve_pntr; + TF1* chan2_HVgaincurve_pntr; + TF1* chan3_HVgaincurve_pntr; + + TF1 m_HVgainCurveMap[4]; + + private: + // Propert that points to the location of the root file which contains the HV gain curves for the calorimeter PMTs + StringProperty m_PMT_HV_Gain_Curve_file{this, "PMT_HV_Gain_Curve_file", "/cvmfs/faser.cern.ch/repo/sw/database/DBRelease/current/pmtgain/CaloGainCurves.root"}; + + // properties that map channel name to PMT HV gain curves. PMt names found at https://twiki.cern.ch/twiki/bin/viewauth/FASER/CaloScintillator + StringProperty m_chan0_HVgaincurve_name{this, "Chan0HVgaincurve", "pol5_HV_Gain_Curve_PMT_LB8770"}; + StringProperty m_chan1_HVgaincurve_name{this, "Chan1HVgaincurve", "pol5_HV_Gain_Curve_PMT_LB8733"}; + StringProperty m_chan2_HVgaincurve_name{this, "Chan2HVgaincurve", "pol5_HV_Gain_Curve_PMT_LB8786"}; + StringProperty m_chan3_HVgaincurve_name{this, "Chan3HVgaincurve", "pol5_HV_Gain_Curve_PMT_LB8732"}; + + // Read Cond Handle + SG::ReadCondHandleKey<CondAttrListCollection> m_PMT_HV_ReadKey{this, "PMT_HV_ReadKey", "/WAVE/Calibration/HV", "Key of folder for PMT HV reading"}; + 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"}; + +}; + +#endif // CALORECTOOLS_CALORECTOOL_H diff --git a/Calorimeter/CaloRecTools/src/components/CaloRecTools_entries.cxx b/Calorimeter/CaloRecTools/src/components/CaloRecTools_entries.cxx new file mode 100644 index 0000000000000000000000000000000000000000..c9c5438eb029be7532820e35dee8e41710f5e781 --- /dev/null +++ b/Calorimeter/CaloRecTools/src/components/CaloRecTools_entries.cxx @@ -0,0 +1,3 @@ +#include "../CaloRecTool.h" + +DECLARE_COMPONENT( CaloRecTool ) diff --git a/Control/CalypsoExample/Digitization/scripts/faserMDC_digi.py b/Control/CalypsoExample/Digitization/scripts/faserMDC_digi.py index 1154edd8aad0cd4ac8daadf5559e05ef1cc362b9..4c7dba7e427cb0b545a0cbc0526ed4b6c6918e76 100755 --- a/Control/CalypsoExample/Digitization/scripts/faserMDC_digi.py +++ b/Control/CalypsoExample/Digitization/scripts/faserMDC_digi.py @@ -81,7 +81,7 @@ elif runtype == "TestBeamMC" : # New TI12 geometry (ugh) elif runtype == "TI12MC": ConfigFlags.GeoModel.FaserVersion = "FASERNU-03" - ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-02" + ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-03" else: print("Invalid run type found:", runtype) diff --git a/Control/CalypsoExample/Digitization/scripts/faserMDC_digi_merge.py b/Control/CalypsoExample/Digitization/scripts/faserMDC_digi_merge.py index a421cead6c379b8dd56fc2d80ea86bb9ca8ab342..8ee8d6f744d79bfdcbf9eb4177a89fc3021583e5 100755 --- a/Control/CalypsoExample/Digitization/scripts/faserMDC_digi_merge.py +++ b/Control/CalypsoExample/Digitization/scripts/faserMDC_digi_merge.py @@ -154,7 +154,7 @@ elif runtype == "TestBeamMC" : # New TI12 geometry (ugh) elif runtype == "TI12MC": ConfigFlags.GeoModel.FaserVersion = "FASERNU-03" - ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-02" + ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-03" else: print("Invalid run type found:", runtype) diff --git a/Control/CalypsoExample/Digitization/scripts/faser_digi.py b/Control/CalypsoExample/Digitization/scripts/faser_digi.py index 72f890a3bd3b7f352f60c66207de15aaa2ec4961..40fb1915d50a8b3e6fd25bb6808b04ef1c5d9c16 100755 --- a/Control/CalypsoExample/Digitization/scripts/faser_digi.py +++ b/Control/CalypsoExample/Digitization/scripts/faser_digi.py @@ -78,7 +78,7 @@ elif runtype == "TestBeamMC" : # New TI12 geometry (ugh) elif runtype == "TI12MC": ConfigFlags.GeoModel.FaserVersion = "FASERNU-03" - ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-02" + ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-03" else: print("Invalid geometry type found:", runtype) diff --git a/Control/CalypsoExample/Digitization/scripts/faser_digi_merge.py b/Control/CalypsoExample/Digitization/scripts/faser_digi_merge.py index ea135db8346438f9a392959d7791744997353a1e..1be2af2d92bcd37edeb2d2d20517e1254069822f 100755 --- a/Control/CalypsoExample/Digitization/scripts/faser_digi_merge.py +++ b/Control/CalypsoExample/Digitization/scripts/faser_digi_merge.py @@ -168,7 +168,7 @@ elif runtype == "TestBeamMC" : # New TI12 geometry (ugh) elif runtype == "TI12MC": ConfigFlags.GeoModel.FaserVersion = "FASERNU-03" - ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-02" + ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-03" else: print("Invalid run type found:", runtype) diff --git a/Control/CalypsoExample/Generation/data/mdc/FaserMC-MDC_PG_muon_fasernu_1000GeV-101312.json b/Control/CalypsoExample/Generation/data/mdc/FaserMC-MDC_PG_muon_fasernu_1000GeV-101312.json new file mode 100644 index 0000000000000000000000000000000000000000..ee3ac4eefd1264fb4553b29090772a1b9353282e --- /dev/null +++ b/Control/CalypsoExample/Generation/data/mdc/FaserMC-MDC_PG_muon_fasernu_1000GeV-101312.json @@ -0,0 +1,14 @@ +{ + "file_length": 5000, + "mass": 105.66, + "maxE": 1000.0, + "minE": 1000.0, + "pid": [-13, 13], + "radius": -25.0, + "angle": 0.0006, + "run": 101312, + "sampler": "const", + "segment": 0, + "short": "MDC_PG_muon_fasernu_1000GeV", + "zpos": -3990.0 +} diff --git a/Control/CalypsoExample/Generation/data/mdc/FaserMC-MDC_PG_muon_fasernu_100GeV-101310.json b/Control/CalypsoExample/Generation/data/mdc/FaserMC-MDC_PG_muon_fasernu_100GeV-101310.json new file mode 100644 index 0000000000000000000000000000000000000000..8c949c0bcdc862ec4b97bfa934e85ad590b78647 --- /dev/null +++ b/Control/CalypsoExample/Generation/data/mdc/FaserMC-MDC_PG_muon_fasernu_100GeV-101310.json @@ -0,0 +1,14 @@ +{ + "file_length": 5000, + "mass": 105.66, + "maxE": 100.0, + "minE": 100.0, + "pid": [-13, 13], + "radius": -25.0, + "angle": 0.0006, + "run": 101310, + "sampler": "const", + "segment": 0, + "short": "MDC_PG_muon_fasernu_100GeV", + "zpos": -3990.0 +} diff --git a/Control/CalypsoExample/Generation/data/mdc/FaserMC-MDC_PG_muon_fasernu_10GeV-101308.json b/Control/CalypsoExample/Generation/data/mdc/FaserMC-MDC_PG_muon_fasernu_10GeV-101308.json new file mode 100644 index 0000000000000000000000000000000000000000..66abf1a6f5a248b875a779e0888d936aa06263b4 --- /dev/null +++ b/Control/CalypsoExample/Generation/data/mdc/FaserMC-MDC_PG_muon_fasernu_10GeV-101308.json @@ -0,0 +1,14 @@ +{ + "file_length": 5000, + "mass": 105.66, + "maxE": 10.0, + "minE": 10.0, + "pid": [-13, 13], + "radius": -25.0, + "angle": 0.0006, + "run": 101308, + "sampler": "const", + "segment": 0, + "short": "MDC_PG_muon_fasernu_10GeV", + "zpos": -3990.0 +} diff --git a/Control/CalypsoExample/Generation/data/mdc/FaserMC-MDC_PG_muon_fasernu_300GeV-101311.json b/Control/CalypsoExample/Generation/data/mdc/FaserMC-MDC_PG_muon_fasernu_300GeV-101311.json new file mode 100644 index 0000000000000000000000000000000000000000..5307647e9ca6c5a3d0b1fa311dc0800b23febf51 --- /dev/null +++ b/Control/CalypsoExample/Generation/data/mdc/FaserMC-MDC_PG_muon_fasernu_300GeV-101311.json @@ -0,0 +1,14 @@ +{ + "file_length": 5000, + "mass": 105.66, + "maxE": 300.0, + "minE": 300.0, + "pid": [-13, 13], + "radius": -25.0, + "angle": 0.0006, + "run": 101311, + "sampler": "const", + "segment": 0, + "short": "MDC_PG_muon_fasernu_300GeV", + "zpos": -3990.0 +} diff --git a/Control/CalypsoExample/Generation/data/mdc/FaserMC-MDC_PG_muon_fasernu_30GeV-101309.json b/Control/CalypsoExample/Generation/data/mdc/FaserMC-MDC_PG_muon_fasernu_30GeV-101309.json new file mode 100644 index 0000000000000000000000000000000000000000..6eda07ec333b0ef2a0685c7cd7d9b6120e65ed43 --- /dev/null +++ b/Control/CalypsoExample/Generation/data/mdc/FaserMC-MDC_PG_muon_fasernu_30GeV-101309.json @@ -0,0 +1,14 @@ +{ + "file_length": 5000, + "mass": 105.66, + "maxE": 30.0, + "minE": 30.0, + "pid": [-13, 13], + "radius": -25.0, + "angle": 0.0006, + "run": 101309, + "sampler": "const", + "segment": 0, + "short": "MDC_PG_muon_fasernu_30GeV", + "zpos": -3990.0 +} diff --git a/Control/CalypsoExample/Generation/data/mdc/FaserMC-MDC_PG_pion_fasernu_1000GeV-121106.json b/Control/CalypsoExample/Generation/data/mdc/FaserMC-MDC_PG_pion_fasernu_1000GeV-121106.json new file mode 100644 index 0000000000000000000000000000000000000000..513974d4cdbdcc23e5750a06d382a0633c9a2bf1 --- /dev/null +++ b/Control/CalypsoExample/Generation/data/mdc/FaserMC-MDC_PG_pion_fasernu_1000GeV-121106.json @@ -0,0 +1,14 @@ +{ + "file_length": 500, + "mass": 105.66, + "maxE": 1000.0, + "minE": 1000.0, + "pid": [211, -211], + "radius": -25.0, + "angle": 0.0006, + "run": 121106, + "sampler": "const", + "segment": 0, + "short": "MDC_PG_pion_fasernu_1000GeV", + "zpos": -3990.0 +} diff --git a/Control/CalypsoExample/Generation/data/mdc/FaserMC-MDC_PG_pion_fasernu_100GeV-121104.json b/Control/CalypsoExample/Generation/data/mdc/FaserMC-MDC_PG_pion_fasernu_100GeV-121104.json new file mode 100644 index 0000000000000000000000000000000000000000..79b23b151fa1cfce149904689cd1c220ac9ea4e2 --- /dev/null +++ b/Control/CalypsoExample/Generation/data/mdc/FaserMC-MDC_PG_pion_fasernu_100GeV-121104.json @@ -0,0 +1,14 @@ +{ + "file_length": 1000, + "mass": 105.66, + "maxE": 100.0, + "minE": 100.0, + "pid": [211, -211], + "radius": -25.0, + "angle": 0.0006, + "run": 121104, + "sampler": "const", + "segment": 0, + "short": "MDC_PG_pion_fasernu_100GeV", + "zpos": -3990.0 +} diff --git a/Control/CalypsoExample/Generation/data/mdc/FaserMC-MDC_PG_pion_fasernu_10GeV-121102.json b/Control/CalypsoExample/Generation/data/mdc/FaserMC-MDC_PG_pion_fasernu_10GeV-121102.json new file mode 100644 index 0000000000000000000000000000000000000000..7cec4dd2dcbb6af17ac8a26efb3a90e2d2b6b6ab --- /dev/null +++ b/Control/CalypsoExample/Generation/data/mdc/FaserMC-MDC_PG_pion_fasernu_10GeV-121102.json @@ -0,0 +1,14 @@ +{ + "file_length": 1000, + "mass": 105.66, + "maxE": 10.0, + "minE": 10.0, + "pid": [211, -211], + "radius": -25.0, + "angle": 0.0006, + "run": 121102, + "sampler": "const", + "segment": 0, + "short": "MDC_PG_pion_fasernu_10GeV", + "zpos": -3990.0 +} diff --git a/Control/CalypsoExample/Generation/data/mdc/FaserMC-MDC_PG_pion_fasernu_300GeV-121105.json b/Control/CalypsoExample/Generation/data/mdc/FaserMC-MDC_PG_pion_fasernu_300GeV-121105.json new file mode 100644 index 0000000000000000000000000000000000000000..255af7e27c014ffc94b16b068af5bc90fb45e824 --- /dev/null +++ b/Control/CalypsoExample/Generation/data/mdc/FaserMC-MDC_PG_pion_fasernu_300GeV-121105.json @@ -0,0 +1,14 @@ +{ + "file_length": 1000, + "mass": 105.66, + "maxE": 300.0, + "minE": 300.0, + "pid": [211, -211], + "radius": -25.0, + "angle": 0.0006, + "run": 121105, + "sampler": "const", + "segment": 0, + "short": "MDC_PG_pion_fasernu_300GeV", + "zpos": -3990.0 +} diff --git a/Control/CalypsoExample/Generation/data/mdc/FaserMC-MDC_PG_pion_fasernu_30GeV-121103.json b/Control/CalypsoExample/Generation/data/mdc/FaserMC-MDC_PG_pion_fasernu_30GeV-121103.json new file mode 100644 index 0000000000000000000000000000000000000000..6c25133024940086163302a453aff06e15153f76 --- /dev/null +++ b/Control/CalypsoExample/Generation/data/mdc/FaserMC-MDC_PG_pion_fasernu_30GeV-121103.json @@ -0,0 +1,14 @@ +{ + "file_length": 1000, + "mass": 105.66, + "maxE": 30.0, + "minE": 30.0, + "pid": [211, -211], + "radius": -25.0, + "angle": 0.0006, + "run": 121103, + "sampler": "const", + "segment": 0, + "short": "MDC_PG_pion_fasernu_30GeV", + "zpos": -3990.0 +} diff --git a/Control/CalypsoExample/Generation/scripts/faserMDC_foresee.py b/Control/CalypsoExample/Generation/scripts/faserMDC_foresee.py index f16b6a40a0413278097824bb7af63b51811eaa9c..bec911031cfec291fe523d5ded2916c688538ea2 100755 --- a/Control/CalypsoExample/Generation/scripts/faserMDC_foresee.py +++ b/Control/CalypsoExample/Generation/scripts/faserMDC_foresee.py @@ -76,7 +76,7 @@ if __name__ == '__main__': ConfigFlags.addFlag("Sim.Beam.yshift", 12.) ConfigFlags.GeoModel.FaserVersion = "FASERNU-03" # Geometry set-up - ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-02" # Conditions set-up + ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-03" # Conditions set-up ConfigFlags.addFlag("Input.InitialTimeStamp", 0) # To avoid autoconfig ConfigFlags.GeoModel.Align.Dynamic = False diff --git a/Control/CalypsoExample/Generation/scripts/faserMDC_particlegun.py b/Control/CalypsoExample/Generation/scripts/faserMDC_particlegun.py index 98975a548601209a81b932c7cbbbe03da7184035..32d68b601f4fc43ef9d2942efff26f4562e83813 100755 --- a/Control/CalypsoExample/Generation/scripts/faserMDC_particlegun.py +++ b/Control/CalypsoExample/Generation/scripts/faserMDC_particlegun.py @@ -72,7 +72,7 @@ if __name__ == '__main__': ConfigFlags.addFlag("Sim.Beam.yshift", 0) ConfigFlags.GeoModel.FaserVersion = "FASERNU-03" # Geometry set-up - ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-02" # Conditions set-up + ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-03" # Conditions set-up ConfigFlags.addFlag("Input.InitialTimeStamp", 0) # To avoid autoconfig ConfigFlags.GeoModel.Align.Dynamic = False diff --git a/Control/CalypsoExample/Generation/scripts/faser_particlegun.py b/Control/CalypsoExample/Generation/scripts/faser_particlegun.py index 6abdfdd4a8c8ae18547462b68532bd51cc4a9d71..cc1628efdb9245e32b7abbbc9ca60a60b2151fad 100755 --- a/Control/CalypsoExample/Generation/scripts/faser_particlegun.py +++ b/Control/CalypsoExample/Generation/scripts/faser_particlegun.py @@ -74,8 +74,8 @@ if __name__ == '__main__': if args.geom == "TI12MC": # 2022 TI12 geometry - ConfigFlags.GeoModel.FaserVersion = "FASERNU-02" # Geometry set-up - ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-02" # Conditions set-up + ConfigFlags.GeoModel.FaserVersion = "FASERNU-03" # Geometry set-up + ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-03" # Conditions set-up # TI12 detectors detectors = ['Veto', 'VetoNu', 'Preshower', 'FaserSCT', 'Ecal', 'Trigger', 'Dipole', 'Emulsion', 'Trench'] diff --git a/Control/CalypsoExample/Generation/scripts/submit_faserMDC_particlegun.sh b/Control/CalypsoExample/Generation/scripts/submit_faserMDC_particlegun.sh index 5d704e9a51445d2ae408512c4eb0df83c71a8b39..08f21dbfc5b08fcc1225ef2594099bb0e51f0d38 100755 --- a/Control/CalypsoExample/Generation/scripts/submit_faserMDC_particlegun.sh +++ b/Control/CalypsoExample/Generation/scripts/submit_faserMDC_particlegun.sh @@ -199,7 +199,7 @@ if ! [ -z "$outdest" ] then ls -l echo "copy *-HITS.root to $outdest" - mkdir -p $outdest + eos mkdir -p $outdest eos cp *-HITS.root ${outdest}/ || true fi # @@ -209,13 +209,13 @@ then cd .. ls -l echo "copy $logfile to $logdest" - mkdir -p $logdest + eos mkdir -p $logdest eos cp $logfile $logdest/$logfile elif ! [ -z "$outdest" ] then cd .. ls -l echo "copy $logfile to $outdest" - mkdir -p $outdest + eos mkdir -p $outdest eos cp $logfile $outdest/$logfile fi diff --git a/Control/CalypsoExample/GeoModelTest/python/Faser03TestConfig.py b/Control/CalypsoExample/GeoModelTest/python/Faser03TestConfig.py index 70322eb150975256868a84bf7bd2174697d0a0da..bf562e1b7aba756ebdab8e65568a180321c5de12 100644 --- a/Control/CalypsoExample/GeoModelTest/python/Faser03TestConfig.py +++ b/Control/CalypsoExample/GeoModelTest/python/Faser03TestConfig.py @@ -33,7 +33,7 @@ if __name__ == "__main__": # Flags for this job ConfigFlags.Input.isMC = True # Needed to bypass autoconfig - ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-02" # Always needed; must match FaserVersion + ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-03" # Always needed; must match FaserVersion ConfigFlags.GeoModel.FaserVersion = "FASERNU-03" # Default FASER geometry ConfigFlags.GeoModel.GeoExportFile = "FaserNu03.db" # Writes out a GeoModel file with the full geometry tree (optional, comment out to skip) ConfigFlags.Detector.GeometryEmulsion = True diff --git a/Control/CalypsoExample/Reconstruction/scripts/faserMDC_reco.py b/Control/CalypsoExample/Reconstruction/scripts/faserMDC_reco.py index 6f5b224ee7b2de4bd7dfe66aa277a8b5b755157c..eddc43e211437c8d313510b919a167a7089a2066 100755 --- a/Control/CalypsoExample/Reconstruction/scripts/faserMDC_reco.py +++ b/Control/CalypsoExample/Reconstruction/scripts/faserMDC_reco.py @@ -88,12 +88,12 @@ elif runtype == "TestBeamData" or runtype == "TestBeam2021": # New TI12 geometry (ugh) elif runtype == "TI12Data02": ConfigFlags.GeoModel.FaserVersion = "FASER-02" - ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-02" + ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-03" # Final 2022 TI12 geometry elif runtype == "TI12Data03": ConfigFlags.GeoModel.FaserVersion = "FASERNU-03" - ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-02" + ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-03" else: print("Invalid run type found:", runtype) diff --git a/Control/CalypsoExample/Reconstruction/scripts/faser_reco.py b/Control/CalypsoExample/Reconstruction/scripts/faser_reco.py index 4e233bf4fcb8a014393bf8858c55ef25d7690519..72235c1f2bb0d6f1167e4b12350ecb5214ecd580 100755 --- a/Control/CalypsoExample/Reconstruction/scripts/faser_reco.py +++ b/Control/CalypsoExample/Reconstruction/scripts/faser_reco.py @@ -101,7 +101,11 @@ else: ConfigFlags.Input.ProjectName = "data20" ConfigFlags.GeoModel.Align.Dynamic = False +# Flags for later useCKF = True +useCal = False +useLHC = False + # Enable ACTS material corrections, this crashes testbeam geometries ConfigFlags.TrackingGeometry.MaterialSource = "/cvmfs/faser.cern.ch/repo/sw/database/DBRelease/current/acts/material-maps.json" @@ -115,16 +119,21 @@ elif runtype == "TestBeamData" or runtype == "TestBeamMC": ConfigFlags.GeoModel.FaserVersion = "FASER-TB00" ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-TB00" useCKF = False + useCal = True # New TI12 geometry (ugh) elif runtype == "TI12Data02": ConfigFlags.GeoModel.FaserVersion = "FASER-02" - ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-02" + ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-03" # Final 2022 TI12 geometry elif runtype == "TI12Data03": ConfigFlags.GeoModel.FaserVersion = "FASERNU-03" - ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-02" + # ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-02" + # Use the updated field map + ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-03" + useCal = True + useLHC = True else: print("Invalid run type found:", runtype) @@ -176,13 +185,21 @@ else: from FaserGeoModel.FaserGeoModelConfig import FaserGeometryCfg acc.merge(FaserGeometryCfg(ConfigFlags)) +if useLHC: + from LHCDataAlgs.LHCDataAlgConfig import LHCDataAlgCfg + acc.merge(LHCDataAlgCfg(ConfigFlags)) + # Set up algorithms from WaveRecAlgs.WaveRecAlgsConfig import WaveformReconstructionCfg acc.merge(WaveformReconstructionCfg(ConfigFlags)) -# Not ready for primetime -# from CaloRecAlgs.CaloRecAlgsConfig import CalorimeterReconstructionCfg -# acc.merge(CalorimeterReconstructionCfg(ConfigFlags)) +# Calorimeter reconstruction +if args.isMC: + # Not ready for MC quite yet + pass +elif useCal: + from CaloRecAlgs.CaloRecAlgsConfig import CalorimeterReconstructionCfg + acc.merge(CalorimeterReconstructionCfg(ConfigFlags)) # Tracker clusters from TrackerPrepRawDataFormation.TrackerPrepRawDataFormationConfig import FaserSCT_ClusterizationCfg @@ -230,6 +247,9 @@ itemList = [ "xAOD::EventInfo#*" , "TrackCollection#*" ] # +if useLHC: + itemList.extend( ["xAOD::FaserLHCData#*", "xAOD::FaserLHCDataAux#*"] ) + if args.isMC: # Make xAOD versions of truth from Reconstruction.xAODTruthCnvAlgConfig import xAODTruthCnvAlgCfg @@ -252,8 +272,8 @@ from WaveRecAlgs.WaveRecAlgsConfig import WaveformReconstructionOutputCfg acc.merge(WaveformReconstructionOutputCfg(ConfigFlags)) # Calorimeter reconstruction output -# from CaloRecAlgs.CaloRecAlgsConfig import CalorimeterReconstructionOutputCfg -# acc.merge(CalorimeterReconstructionOutputCfg(ConfigFlags)) +from CaloRecAlgs.CaloRecAlgsConfig import CalorimeterReconstructionOutputCfg +acc.merge(CalorimeterReconstructionOutputCfg(ConfigFlags)) # Check what we have print( "Writing out xAOD objects:" ) diff --git a/Control/CalypsoExample/Reconstruction/scripts/submit_faserMDC_reco.sh b/Control/CalypsoExample/Reconstruction/scripts/submit_faserMDC_reco.sh index e4d93ba6487000c7c939ee57d79dd704dad96324..0f9cb4479a5130508a58f91efd11b3538b97ebf2 100755 --- a/Control/CalypsoExample/Reconstruction/scripts/submit_faserMDC_reco.sh +++ b/Control/CalypsoExample/Reconstruction/scripts/submit_faserMDC_reco.sh @@ -163,7 +163,7 @@ else tagstr="--reco=$tag" fi # -faser_reco.py "--nevents=$nevents" $tagstr "$file_path" +faser_reco.py "--nevents=$nevents" --isMC $tagstr "$file_path" # # Print out ending time date diff --git a/Control/CalypsoExample/SimHitExample/python/SimHitExampleConfig.py b/Control/CalypsoExample/SimHitExample/python/SimHitExampleConfig.py index 5e71b860f80281d8075e993cc3a41c535bfb4c71..aec94afcf8e3007eb454fe0c28f9a2c42ee7ed28 100644 --- a/Control/CalypsoExample/SimHitExample/python/SimHitExampleConfig.py +++ b/Control/CalypsoExample/SimHitExample/python/SimHitExampleConfig.py @@ -32,7 +32,7 @@ if __name__ == "__main__": # Flags for this job ConfigFlags.Input.Files = ["my.HITS.pool.root"] # input file(s) ConfigFlags.Input.isMC = True # Needed to bypass autoconfig - ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-02" # Always needed; must match FaserVersion + ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-03" # Always needed; must match FaserVersion ConfigFlags.GeoModel.FaserVersion = "FASERNU-03" # Default FASER geometry ConfigFlags.Detector.GeometryEmulsion = True ConfigFlags.Detector.GeometryTrench = True diff --git a/Control/CalypsoExample/Simulation/scripts/faserMDC_simulate.py b/Control/CalypsoExample/Simulation/scripts/faserMDC_simulate.py index 0fd9622db5de8630ffaef34bd2ae4b6eabe88a5c..1cdb68251fd2f35df0e66382b76822a9bedfc5ec 100755 --- a/Control/CalypsoExample/Simulation/scripts/faserMDC_simulate.py +++ b/Control/CalypsoExample/Simulation/scripts/faserMDC_simulate.py @@ -147,7 +147,7 @@ if __name__ == '__main__': ConfigFlags.addFlag("Sim.Beam.yshift", args.yshift) ConfigFlags.GeoModel.FaserVersion = "FASERNU-03" # Geometry set-up - ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-02" # Conditions set-up + ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-03" # Conditions set-up ConfigFlags.addFlag("Input.InitialTimeStamp", 0) # To avoid autoconfig ConfigFlags.GeoModel.Align.Dynamic = False diff --git a/Control/CalypsoExample/xAODTruthConversion/scripts/runTruthCnv.py b/Control/CalypsoExample/xAODTruthConversion/scripts/runTruthCnv.py index b51b4d4ba059d571921fe6328e13144ccf104f23..5e63eccee4f4887ff0a986dfe7cdd02e90f59942 100644 --- a/Control/CalypsoExample/xAODTruthConversion/scripts/runTruthCnv.py +++ b/Control/CalypsoExample/xAODTruthConversion/scripts/runTruthCnv.py @@ -52,7 +52,7 @@ if __name__ == "__main__": # Flags for this job ConfigFlags.Input.isMC = True # Needed to bypass autoconfig - ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-02" # Always needed; must match FaserVersion + ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-03" # Always needed; must match FaserVersion ConfigFlags.GeoModel.FaserVersion = "FASERNU-03" # Default FASER geometry ConfigFlags.Input.Files = ['my.HITS.pool.root'] ConfigFlags.Output.doWriteAOD = True diff --git a/Database/ConnectionManagement/FaserAuthentication/CMakeLists.txt b/Database/ConnectionManagement/FaserAuthentication/CMakeLists.txt index ecf7b9bb3985ff15c82df3794cf93b627ccbb915..eb1c72ae4cfdfd5b7a8a8da914da78a154f9446d 100644 --- a/Database/ConnectionManagement/FaserAuthentication/CMakeLists.txt +++ b/Database/ConnectionManagement/FaserAuthentication/CMakeLists.txt @@ -39,6 +39,7 @@ set( FaserAuthentication_home # Apparently not needed, because we don't have it... #atlas_install_xmls( ${FaserAuthentication_home}/authentication.xml ) + # Configure the environment setup module: configure_file( ${CMAKE_CURRENT_SOURCE_DIR}/FaserAuthenticationEnvironmentConfig.cmake.in diff --git a/Database/ConnectionManagement/FaserAuthentication/data/dblookup.xml b/Database/ConnectionManagement/FaserAuthentication/data/dblookup.xml index 958fb2ba600c0384381a06460487cb5e83efac98..1518267eeab17bed6f96f3673f6e309c01401dad 100644 --- a/Database/ConnectionManagement/FaserAuthentication/data/dblookup.xml +++ b/Database/ConnectionManagement/FaserAuthentication/data/dblookup.xml @@ -26,14 +26,24 @@ <service name="sqlite_file:///cvmfs/faser.cern.ch/repo/sw/database/DBRelease/current/sqlite200/CABP200.db" accessMode="read" /> </logicalservice> + <logicalservice name="COOLOFL_DIGITIZER"> + <service name="sqlite_file:data/sqlite200/ALLP200.db" accessMode="read" /> + <service name="sqlite_file:///cvmfs/faser.cern.ch/repo/sw/database/DBRelease/current/sqlite200/ALLP200.db" accessMode="read" /> + </logicalservice> + <logicalservice name="COOLOFL_INDET"> <service name="sqlite_file:data/sqlite200/ALLP200.db" accessMode="read" /> <service name="sqlite_file:///cvmfs/faser.cern.ch/repo/sw/database/DBRelease/current/sqlite200/ALLP200.db" accessMode="read" /> </logicalservice> <logicalservice name="COOLOFL_TRIGGER"> - <service name="sqlite_file:data/sqlite200/ALLP200.db" accessMode="read" /> - <service name="sqlite_file:///cvmfs/faser.cern.ch/repo/sw/database/DBRelease/current/sqlite200/ALLP200.db" accessMode="read" /> + <service name="sqlite_file:data/sqlite200/ALLP200.db" accessMode="read" /> + <service name="sqlite_file:///cvmfs/faser.cern.ch/repo/sw/database/DBRelease/current/sqlite200/ALLP200.db" accessMode="read" /> +</logicalservice> + +<logicalservice name="COOLOFL_LHC"> + <service name="sqlite_file:data/sqlite200/ALLP200.db" accessMode="read" /> + <service name="sqlite_file:///cvmfs/faser.cern.ch/repo/sw/database/DBRelease/current/sqlite200/ALLP200.db" accessMode="read" /> </logicalservice> </servicelist> diff --git a/Derviation/DerivationAlgs/share/runDerive.py b/Derviation/DerivationAlgs/share/runDerive.py index b8b22c187c15a39993a68aa722e5d6bae3362f7b..019c6ad29ec5fc1134723c8219cba3caaa440be9 100644 --- a/Derviation/DerivationAlgs/share/runDerive.py +++ b/Derviation/DerivationAlgs/share/runDerive.py @@ -48,7 +48,7 @@ if __name__ == "__main__": #"/bundle/data/FASER/Ti12data/filter/r0008/007983/Faser-Physics-007983-TrigMask08-r0008-xAOD.root" ] - ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-02" # Always needed; must match FaserVersionS + ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-03" # Always needed; must match FaserVersionS ConfigFlags.IOVDb.DatabaseInstance = "OFLP200" # Use MC conditions for now ConfigFlags.Input.ProjectName = "data21" # Needed to bypass autoconfig ConfigFlags.Input.isMC = False # Needed to bypass autoconfig diff --git a/Derviation/DerivationAlgs/share/run_streaming.py b/Derviation/DerivationAlgs/share/run_streaming.py index 3ebacb7892ab51e1d2b5c775bae917dd9e4fa6c3..13fcf2d7011a32bd8a3f14f166c8ff86ca5596a5 100644 --- a/Derviation/DerivationAlgs/share/run_streaming.py +++ b/Derviation/DerivationAlgs/share/run_streaming.py @@ -23,7 +23,7 @@ if __name__ == "__main__": "/eos/experiment/faser/rec/2022/p0008/007984/Faser-Physics-007984-00000-p0008-xAOD.root" ] - ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-02" # Always needed; must match FaserVersionS + ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-03" # Always needed; must match FaserVersionS ConfigFlags.IOVDb.DatabaseInstance = "OFLP200" # Use MC conditions for now ConfigFlags.Input.ProjectName = "data21" # Needed to bypass autoconfig ConfigFlags.Input.isMC = False # Needed to bypass autoconfig diff --git a/DetectorDescription/GeoModel/FaserGeoModel/python/GeoModelInit.py b/DetectorDescription/GeoModel/FaserGeoModel/python/GeoModelInit.py index fbee2144d985412d2624d31e745eec881f3fb54d..4823fcde4cd212a0f3e6446bf690e29c8cf90616 100644 --- a/DetectorDescription/GeoModel/FaserGeoModel/python/GeoModelInit.py +++ b/DetectorDescription/GeoModel/FaserGeoModel/python/GeoModelInit.py @@ -95,9 +95,9 @@ def _setupGeoModel(): # Deal with SCT alignment conditions folders and algorithms - #conddb.addFolderSplitOnline("SCT","/Tracker/Onl/Align","/Tracker/Align",className="AlignableTransformContainer") - print("Override Alignment dbname to OFLP200, fix this when alignment available in CONDBR3") - conddb.addFolder("/Tracker/Align", "SCT_OFL",className="AlignableTransformContainer") + conddb.addFolderSplitOnline("SCT","/Tracker/Onl/Align","/Tracker/Align",className="AlignableTransformContainer") + # print("Override Alignment dbname to OFLP200, fix this when alignment available in CONDBR3") + # conddb.addFolder("/Tracker/Align", "SCT_OFL",className="AlignableTransformContainer") from AthenaCommon.AlgSequence import AthSequencer condSeq = AthSequencer("AthCondSeq") if not hasattr(condSeq, "FaserSCT_AlignCondAlg"): diff --git a/LHCData/LHCDataAlgs/CMakeLists.txt b/LHCData/LHCDataAlgs/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..17abef2b21c0be98b310d45ed210fba0c52421db --- /dev/null +++ b/LHCData/LHCDataAlgs/CMakeLists.txt @@ -0,0 +1,19 @@ +############################################################################### +# Package: LHCDataAlgs +################################################################################ + +# Declare the package name: +atlas_subdir( LHCDataAlgs ) + +# External dependencies: +find_package( Boost COMPONENTS filesystem thread system ) + +# Component(s) in the package: +atlas_add_component( LHCDataAlgs + src/*.h + src/*.cxx + src/components/*.cxx + LINK_LIBRARIES AthenaBaseComps StoreGateLib xAODFaserLHC LHCDataToolsLib ) + +# Install files from the package: +atlas_install_python_modules( python/*.py ) diff --git a/LHCData/LHCDataAlgs/python/LHCDataAlgConfig.py b/LHCData/LHCDataAlgs/python/LHCDataAlgConfig.py new file mode 100644 index 0000000000000000000000000000000000000000..195fbbd12fe448c71e544bc619d503b7a468eae6 --- /dev/null +++ b/LHCData/LHCDataAlgs/python/LHCDataAlgConfig.py @@ -0,0 +1,20 @@ +# Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration +from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator +from AthenaConfiguration.ComponentFactory import CompFactory + +from LHCDataTools.LHCDataToolsConfig import LHCDataCfg + +#LHCDataTool = CompFactory.LHCDataTool + +def LHCDataAlgCfg(flags, name="LHCDataAlg", **kwargs): + + acc = ComponentAccumulator() + + tool = CompFactory.LHCDataTool(name="LHCDataTool") + alg = CompFactory.LHCDataAlg(name, **kwargs) + alg.LHCDataTool = tool + + acc.addEventAlgo(alg) + acc.merge(LHCDataCfg(flags)) + + return acc diff --git a/LHCData/LHCDataAlgs/src/LHCDataAlg.cxx b/LHCData/LHCDataAlgs/src/LHCDataAlg.cxx new file mode 100644 index 0000000000000000000000000000000000000000..de22698589abfbbbfc2ea9aa6d54feacd4661610 --- /dev/null +++ b/LHCData/LHCDataAlgs/src/LHCDataAlg.cxx @@ -0,0 +1,237 @@ +#include "LHCDataAlg.h" + +#include "xAODFaserLHC/FaserLHCDataAux.h" + +LHCDataAlg::LHCDataAlg(const std::string& name, ISvcLocator* pSvcLocator) + : AthReentrantAlgorithm(name, pSvcLocator) { +} + +StatusCode +LHCDataAlg::initialize() { + ATH_MSG_INFO(name() << "::initalize()" ); + + // Initalize tools + ATH_CHECK( m_lhcTool.retrieve() ); + + // Read handle + ATH_CHECK( m_eventInfo.initialize() ); + + // Write handle + ATH_CHECK( m_lhcDataKey.initialize() ); + + return StatusCode::SUCCESS; +} + +StatusCode +LHCDataAlg::finalize() { + return StatusCode::SUCCESS; +} + +StatusCode +LHCDataAlg::execute(const EventContext& ctx) const { + + ATH_MSG_DEBUG("Executing"); + + SG::WriteHandle<xAOD::FaserLHCData> lhcDataHandle(m_lhcDataKey, ctx); + ATH_CHECK( lhcDataHandle.record( std::make_unique<xAOD::FaserLHCData>(), + std::make_unique<xAOD::FaserLHCDataAux>() ) ); + + ATH_MSG_DEBUG("FaserLHCData " << lhcDataHandle.name() << " initialized"); + + lhcDataHandle->set_fillNumber(m_lhcTool->getFillNumber(ctx)); + lhcDataHandle->set_machineMode(m_lhcTool->getMachineMode(ctx)); + lhcDataHandle->set_beamMode(m_lhcTool->getBeamMode(ctx)); + lhcDataHandle->set_beamType1(m_lhcTool->getBeamType1(ctx)); + lhcDataHandle->set_beamType2(m_lhcTool->getBeamType2(ctx)); + + lhcDataHandle->set_betaStar(m_lhcTool->getBetaStar(ctx)); + lhcDataHandle->set_crossingAngle(m_lhcTool->getCrossingAngle(ctx)); + + lhcDataHandle->set_stableBeams(m_lhcTool->getStableBeams(ctx)); + lhcDataHandle->set_injectionScheme(m_lhcTool->getInjectionScheme(ctx)); + + // Slight naming mismatch here, but oh well + lhcDataHandle->set_numBunchBeam1(m_lhcTool->getBeam1Bunches(ctx)); + lhcDataHandle->set_numBunchBeam2(m_lhcTool->getBeam2Bunches(ctx)); + lhcDataHandle->set_numBunchColliding(m_lhcTool->getCollidingBunches(ctx)); + + // Fill BCID information + + // Get the BCID mask + std::vector<unsigned char> bcid_mask = m_lhcTool->getBCIDMasks(ctx); + + // Get the event bcid value + SG::ReadHandle<xAOD::EventInfo> xevt(m_eventInfo, ctx); + unsigned int bcid = xevt->bcid(); + + int nearest = findNearest(bcid, bcid_mask, 3); // Colliding beams + lhcDataHandle->set_distanceToCollidingBCID(nearest); + ATH_MSG_DEBUG("Found distance of " << nearest << " from BCID " << bcid + << " to the nearest colliding BCID "); + + nearest = findNearest(bcid, bcid_mask, 1); // Beam1 unpaired + lhcDataHandle->set_distanceToUnpairedB1(nearest); + ATH_MSG_DEBUG("Found distance of " << nearest << " from BCID " << bcid + << " to the nearest unpaired B1 "); + + nearest = findNearest(bcid, bcid_mask, 2); // Beam2 unpaired + lhcDataHandle->set_distanceToUnpairedB2(nearest); + ATH_MSG_DEBUG("Found distance of " << nearest << " from BCID " << bcid + << " to the nearest unpaired B2 "); + + // Add 127 to current BCID to check if inbound B1 is nearby FASER + int offset_bcid = (bcid + 127) % 3564; + nearest = findNearest(offset_bcid, bcid_mask, 1); // Inbound B1 + int nearest2 = findNearest(offset_bcid, bcid_mask, 3); // Inbound B1 + if (abs(nearest2) < abs(nearest)) nearest = nearest2; + lhcDataHandle->set_distanceToInboundB1(nearest); + ATH_MSG_DEBUG("Found distance of " << nearest << " from BCID " << bcid + << " to the nearest inbound B1 "); + + unsigned int previous; + previous = previousColliding(bcid, bcid_mask); + lhcDataHandle->set_distanceToPreviousColliding(previous); + ATH_MSG_DEBUG("Found distance of " << previous << " from BCID " << bcid + << " to the previous colliding bunch "); + + previous = previousTrain(bcid, bcid_mask); + lhcDataHandle->set_distanceToTrainStart(previous); + ATH_MSG_DEBUG("Found distance of " << previous << " from BCID " << bcid + << " to the start of the previous train "); + + return StatusCode::SUCCESS; +} + +// Function to find distance to nearest BCID +// mask indicates the condition: 1 - unpaired B1, 2 - unpaired B2, 3 - colliding +int +LHCDataAlg::findNearest(unsigned int bcid, const std::vector<unsigned char>& bcid_mask, unsigned char mask) const { + + // Does the BCID make sense? + if ((bcid > 3564) || (bcid <= 0)) { + ATH_MSG_WARNING("Requested distance from invalid BCID " << bcid << "!"); + return -3565; + } + + unsigned int test_bcid; + + // Move outwards from the bcid (starting at offset of 0) + for (unsigned int i=0; i < 3564/2; i++) { + + // Try positive offsets + test_bcid = (bcid + i) % 3564; + + // BCID 0 doesn't exist in the real machine + // BCID 3564 doesn't exist in our array (but will always be empty in real machine) + // So avoid these pathologies + if (test_bcid != 0) + if (mask == bcid_mask[test_bcid]) return i; + + if(i == 0) continue; // No need to check -0 + + // Try negative offsets + test_bcid = (bcid - i) % 3564; + + // BCID 0 doesn't exist in the real machine + // BCID 3564 doesn't exist in our array (but will always be empty) + // So avoid these pathologies + if (test_bcid != 0) + if (mask == bcid_mask[test_bcid]) return -i; + + } + + // If we got to here, there was no match + // Does the BCID make sense? + ATH_MSG_WARNING("Couldn't find distance from BCID " << bcid << " and pattern " << mask << "!"); + ATH_MSG_WARNING(bcid_mask); + return -3565; + +} + +// Function to find previous colliding BCID +unsigned int +LHCDataAlg::previousColliding(unsigned int bcid, const std::vector<unsigned char>& bcid_mask) const { + + // Does the BCID make sense? + if ((bcid > 3564) || (bcid <= 0)) { + ATH_MSG_WARNING("Requested distance from invalid BCID " << bcid << "!"); + return 9999; + } + + unsigned int test_bcid; + + // Move backwards from the bcid (starting at offset of 0) + for (unsigned int i=0; i < 3564; i++) { + + // Try positive offsets + test_bcid = (bcid - i) % 3564; + + // BCID 3564 doesn't exist in our array (but will always be empty) + // So avoid these pathologies + if (test_bcid != 0) + if (0x03 == bcid_mask[test_bcid]) return i; + + } + + // If we got to here, there was no match + // Does the BCID make sense? + ATH_MSG_WARNING("Couldn't find colliding from BCID " << bcid << "!"); + ATH_MSG_WARNING(bcid_mask); + return 9999; + +} + +unsigned int +LHCDataAlg::previousTrain(unsigned int bcid, const std::vector<unsigned char>& bcid_mask) const { + + // Does the BCID make sense? + if ((bcid > 3564) || (bcid <= 0)) { + ATH_MSG_WARNING("Requested distance from invalid BCID " << bcid << "!"); + return 9999; + } + + unsigned int test_bcid; + + bool in_train = false; + // Move backwards from the bcid (starting at offset of 0) + for (unsigned int i=0; i < 3564; i++) { + + // BCID to test + test_bcid = (bcid - i) % 3564; + + // BCID 3564 doesn't exist in our array (but will always be empty) + // So avoid these pathologies + ATH_MSG_DEBUG("Test " << test_bcid << " In train: " << in_train << " mask[test_bcid]"); + + // If we are not in a train before, lets see if we are in a train now + if (!in_train) { + + // If we found a colliding bunch, set in_train, otherwise we are still not in a train + if ((test_bcid != 0) && (0x03 == bcid_mask[test_bcid])) + in_train = true; + + // Either way, move to next BCID + continue; + + } else { + + // Currently in a train, lets see if now we are not + if ((test_bcid == 0) || (0x03 != bcid_mask[test_bcid])) { + in_train = false; + // Previous BCID was first in train + return i-1; + } else { + in_train = true; + } + + } + + } + + // If we got to here, there was no match + // Does the BCID make sense? + ATH_MSG_WARNING("Couldn't find first in train from BCID " << bcid << "!"); + ATH_MSG_WARNING(bcid_mask); + return 9999; + +} diff --git a/LHCData/LHCDataAlgs/src/LHCDataAlg.h b/LHCData/LHCDataAlgs/src/LHCDataAlg.h new file mode 100644 index 0000000000000000000000000000000000000000..a8785725aad2eec117a51e87ba54b83e5bd5ef4f --- /dev/null +++ b/LHCData/LHCDataAlgs/src/LHCDataAlg.h @@ -0,0 +1,47 @@ +#ifndef LHCDATAALG_H +#define LHCDATAALG_H + +#include "AthenaBaseComps/AthReentrantAlgorithm.h" + +#include "StoreGate/ReadCondHandleKey.h" +#include "StoreGate/WriteCondHandleKey.h" + +#include "GaudiKernel/ToolHandle.h" +#include "GaudiKernel/ICondSvc.h" +#include "GaudiKernel/ServiceHandle.h" + +#include "xAODFaserLHC/FaserLHCData.h" +#include "xAODEventInfo/EventInfo.h" + +#include "LHCDataTools/ILHCDataTool.h" + +class LHCDataAlg : public AthReentrantAlgorithm { + public: + LHCDataAlg(const std::string& name, ISvcLocator* pSvcLocator); + virtual ~LHCDataAlg() = default; + + virtual StatusCode initialize() override; + virtual StatusCode execute(const EventContext& ctx) const override; + virtual StatusCode finalize() override; + virtual bool isClonable() const override { return true; }; + + private: + ToolHandle<ILHCDataTool> m_lhcTool{this, "LHCDataTool", "LHCDataTool"}; + SG::ReadHandleKey<xAOD::EventInfo> m_eventInfo{ this, "EventInfoKey", "EventInfo", "ReadHandleKey for xAOD::EventInfo"}; + SG::WriteHandleKey<xAOD::FaserLHCData> m_lhcDataKey + {this, "FaserLHCDataKey", "FaserLHCData"}; + + // Utility function to find nearest BCID + int findNearest(unsigned int bcid, const std::vector<unsigned char>& bcid_mask, + unsigned char mask) const; + + unsigned int + previousColliding(unsigned int bcid, const std::vector<unsigned char>& bcid_mask) const; + + // Find the distance to the first BCID of the previous train + unsigned int + previousTrain(unsigned int bcid, const std::vector<unsigned char>& bcid_mask) const; + +}; + +#endif // LHCDATAALG_H diff --git a/LHCData/LHCDataAlgs/src/components/LHCDataAlgs_entries.cxx b/LHCData/LHCDataAlgs/src/components/LHCDataAlgs_entries.cxx new file mode 100644 index 0000000000000000000000000000000000000000..1620e8dcfc1af5dc0ae3f2bc4af406684b120896 --- /dev/null +++ b/LHCData/LHCDataAlgs/src/components/LHCDataAlgs_entries.cxx @@ -0,0 +1,3 @@ +#include "../LHCDataAlg.h" + +DECLARE_COMPONENT( LHCDataAlg ) diff --git a/LHCData/LHCDataTools/CMakeLists.txt b/LHCData/LHCDataTools/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..248abc91d58df409f4bc1e65324743c2f66755dd --- /dev/null +++ b/LHCData/LHCDataTools/CMakeLists.txt @@ -0,0 +1,27 @@ +############################################################################### +# Package: LHCDataTools +################################################################################ + +# Declare the package name: +atlas_subdir( LHCDataTools ) + +# External dependencies: +find_package( CLHEP ) +find_package( ROOT COMPONENTS Core Tree MathCore Hist RIO pthread ) + +# Component(s) in the package: +atlas_add_component ( LHCDataTools + src/components/*.cxx + INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS} + LINK_LIBRARIES ${ROOT_LIBRARIES} ${CLHEP_LIBRARIES} AthenaKernel LHCDataToolsLib GaudiKernel AthenaBaseComps AthenaPoolUtilities StoreGateLib xAODEventInfo ) + + +atlas_add_library( LHCDataToolsLib + src/*.cxx + PUBLIC_HEADERS LHCDataTools + INCLUDE_DIRS ${ROOT_INCLUDE_DIRS} ${CLHEP_INCLUDE_DIRS} + LINK_LIBRARIES ${ROOT_LIBRARIES} ${CLHEP_LIBRARIES} AthenaKernel GaudiKernel AthenaBaseComps AthenaPoolUtilities StoreGateLib xAODEventInfo ) + +# Install files from the package: +atlas_install_python_modules( python/*.py ) + diff --git a/LHCData/LHCDataTools/LHCDataTools/ILHCDataTool.h b/LHCData/LHCDataTools/LHCDataTools/ILHCDataTool.h new file mode 100644 index 0000000000000000000000000000000000000000..6e469d0ebecd41d08333d20eb0778f5bfef5d404 --- /dev/null +++ b/LHCData/LHCDataTools/LHCDataTools/ILHCDataTool.h @@ -0,0 +1,75 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS and FAsER collaborations +*/ + +/** @file ILHCDataTool.h Interface file for LHCDataTool. + */ + +// Multiple inclusion protection +#ifndef ILHCDATATOOL +#define ILHCDATATOOL + +//STL includes +#include <map> + +//Gaudi Includes +#include "GaudiKernel/IAlgTool.h" +#include "GaudiKernel/EventContext.h" + +class ILHCDataTool: virtual public IAlgTool { + + public: + + //----------Public Member Functions----------// + // Structors + virtual ~ILHCDataTool() = default; //!< Destructor + + /// Creates the InterfaceID and interfaceID() method + DeclareInterfaceID(ILHCDataTool, 1, 0); + + // Methods to return fill data + virtual int getFillNumber(const EventContext& ctx) const = 0; + virtual int getFillNumber(void) const = 0; + + virtual std::string getMachineMode(const EventContext& ctx) const = 0; + virtual std::string getMachineMode(void) const = 0; + + virtual std::string getInjectionScheme(const EventContext& ctx) const = 0; + virtual std::string getInjectionScheme(void) const = 0; + + virtual int getBeamType1(const EventContext& ctx) const = 0; + virtual int getBeamType1(void) const = 0; + + virtual int getBeamType2(const EventContext& ctx) const = 0; + virtual int getBeamType2(void) const = 0; + + // Methods to return beam data + virtual std::string getBeamMode(const EventContext& ctx) const = 0; + virtual std::string getBeamMode(void) const = 0; + + virtual float getBetaStar(const EventContext& ctx) const = 0; + virtual float getBetaStar(void) const = 0; + + virtual float getCrossingAngle(const EventContext& ctx) const = 0; + virtual float getCrossingAngle(void) const = 0; + + virtual bool getStableBeams(const EventContext& ctx) const = 0; + virtual bool getStableBeams(void) const = 0; + + // Methods to return BCID data + virtual unsigned int getBeam1Bunches(const EventContext& ctx) const = 0; + virtual unsigned int getBeam1Bunches(void) const = 0; + + virtual unsigned int getBeam2Bunches(const EventContext& ctx) const = 0; + virtual unsigned int getBeam2Bunches(void) const = 0; + + virtual unsigned int getCollidingBunches(const EventContext& ctx) const = 0; + virtual unsigned int getCollidingBunches(void) const = 0; + + virtual std::vector<unsigned char> getBCIDMasks(const EventContext& ctx) const = 0; + virtual std::vector<unsigned char> getBCIDMasks(void) const = 0; + +}; + +//---------------------------------------------------------------------- +#endif // LHCDATATOOL diff --git a/LHCData/LHCDataTools/python/LHCDataToolsConfig.py b/LHCData/LHCDataTools/python/LHCDataToolsConfig.py new file mode 100644 index 0000000000000000000000000000000000000000..cdd2d267cb63d5ba05378eff252afe4c6d97fe8e --- /dev/null +++ b/LHCData/LHCDataTools/python/LHCDataToolsConfig.py @@ -0,0 +1,19 @@ +# Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration +from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator +from AthenaConfiguration.ComponentFactory import CompFactory +from IOVDbSvc.IOVDbSvcConfig import addFolders + +def LHCDataCfg(flags, **kwargs): + acc = ComponentAccumulator() + dbInstance = kwargs.get("dbInstance", "COOLOFL_LHC") + dbName = flags.IOVDb.DatabaseInstance # e.g. CONDBR3 + + #acc.merge(addFolders(flags, folder_list, dbInstance, className="AthenaAttributeList")) + # COOLOFL_LHC is not known to ATLAS IOVDBSvc + # Must use non-shorthand folder specification here + folder_list = ["/LHC/FillData", "/LHC/BeamData", "/LHC/BCIDData"] + for folder_name in folder_list: + folder_string = f"<db>{dbInstance}/{dbName}</db> {folder_name}" + acc.merge(addFolders(flags, folder_string, className="AthenaAttributeList")) + return acc + diff --git a/LHCData/LHCDataTools/src/LHCDataTool.cxx b/LHCData/LHCDataTools/src/LHCDataTool.cxx new file mode 100644 index 0000000000000000000000000000000000000000..7b0fafe00d7137d0d62e81c28f77d812d2501001 --- /dev/null +++ b/LHCData/LHCDataTools/src/LHCDataTool.cxx @@ -0,0 +1,237 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS and FASER collaborations +*/ + +/** @file LHCDataTool.cxx Implementation file for LHCDataTool. + @author Eric Torrence (05/02/22) +*/ + +#include "LHCDataTool.h" +#include "CoralBase/Blob.h" + +//---------------------------------------------------------------------- +LHCDataTool::LHCDataTool (const std::string& type, const std::string& name, const IInterface* parent) : + base_class(type, name, parent) +{ +} + +//---------------------------------------------------------------------- +StatusCode +LHCDataTool::initialize() { + + ATH_MSG_DEBUG("LHCDataTool::initialize()"); + + // Read Handles + //ATH_CHECK(m_fillDataKey.initialize()); + ATH_CHECK(m_beamDataKey.initialize()); + ATH_CHECK(m_bcidDataKey.initialize()); + + return StatusCode::SUCCESS; +} + +//---------------------------------------------------------------------- +StatusCode +LHCDataTool::finalize() { + // Print where you are + return StatusCode::SUCCESS; +} + +//---------------------------------------------------------------------- +int +LHCDataTool::getFillNumber(const EventContext& ctx) const { + // Read Cond Handle + SG::ReadCondHandle<AthenaAttributeList> readHandle{m_beamDataKey, ctx}; + return (**readHandle)["FillNumber"].data<int>(); +} + +int +LHCDataTool::getFillNumber(void) const { + const EventContext& ctx{Gaudi::Hive::currentContext()}; + return getFillNumber(ctx); +} + +//---------------------------------------------------------------------- +std::string +LHCDataTool::getMachineMode(const EventContext& ctx) const { + // Read Cond Handle + SG::ReadCondHandle<AthenaAttributeList> readHandle{m_beamDataKey, ctx}; + return (**readHandle)["MachineMode"].data<std::string>(); +} + +std::string +LHCDataTool::getMachineMode(void) const { + const EventContext& ctx{Gaudi::Hive::currentContext()}; + return getMachineMode(ctx); +} + +//---------------------------------------------------------------------- +std::string +LHCDataTool::getBeamMode(const EventContext& ctx) const { + SG::ReadCondHandle<AthenaAttributeList> readHandle{m_beamDataKey, ctx}; + return(**readHandle)["BeamMode"].data<std::string>(); +} + +std::string +LHCDataTool::getBeamMode(void) const { + const EventContext& ctx{Gaudi::Hive::currentContext()}; + return getBeamMode(ctx); +} + +//---------------------------------------------------------------------- +int +LHCDataTool::getBeamType1(const EventContext& ctx) const { + // Read Cond Handle + SG::ReadCondHandle<AthenaAttributeList> readHandle{m_beamDataKey, ctx}; + return (**readHandle)["BeamType1"].data<int>(); +} + +int +LHCDataTool::getBeamType1(void) const { + const EventContext& ctx{Gaudi::Hive::currentContext()}; + return getBeamType1(ctx); +} + +//---------------------------------------------------------------------- +int +LHCDataTool::getBeamType2(const EventContext& ctx) const { + // Read Cond Handle + SG::ReadCondHandle<AthenaAttributeList> readHandle{m_beamDataKey, ctx}; + return (**readHandle)["BeamType2"].data<int>(); +} + +int +LHCDataTool::getBeamType2(void) const { + const EventContext& ctx{Gaudi::Hive::currentContext()}; + return getBeamType2(ctx); +} + +//---------------------------------------------------------------------- +float +LHCDataTool::getBetaStar(const EventContext& ctx) const { + SG::ReadCondHandle<AthenaAttributeList> readHandle{m_beamDataKey, ctx}; + return(**readHandle)["BetaStar"].data<float>(); +} + +float +LHCDataTool::getBetaStar(void) const { + const EventContext& ctx{Gaudi::Hive::currentContext()}; + return getBetaStar(ctx); +} + +//---------------------------------------------------------------------- +float +LHCDataTool::getCrossingAngle(const EventContext& ctx) const { + SG::ReadCondHandle<AthenaAttributeList> readHandle{m_beamDataKey, ctx}; + return(**readHandle)["CrossingAngle"].data<float>(); +} + +float +LHCDataTool::getCrossingAngle(void) const { + const EventContext& ctx{Gaudi::Hive::currentContext()}; + return getCrossingAngle(ctx); +} + +//---------------------------------------------------------------------- +bool +LHCDataTool::getStableBeams(const EventContext& ctx) const { + SG::ReadCondHandle<AthenaAttributeList> readHandle{m_beamDataKey, ctx}; + return(**readHandle)["StableBeams"].data<bool>(); +} + +bool +LHCDataTool::getStableBeams(void) const { + const EventContext& ctx{Gaudi::Hive::currentContext()}; + return getStableBeams(ctx); +} + +//---------------------------------------------------------------------- +std::string +LHCDataTool::getInjectionScheme(const EventContext& ctx) const { + // Read Cond Handle + SG::ReadCondHandle<AthenaAttributeList> readHandle{m_beamDataKey, ctx}; + return (**readHandle)["InjectionScheme"].data<std::string>(); +} + +std::string +LHCDataTool::getInjectionScheme(void) const { + const EventContext& ctx{Gaudi::Hive::currentContext()}; + return getInjectionScheme(ctx); +} + +//---------------------------------------------------------------------- +unsigned int +LHCDataTool::getBeam1Bunches(const EventContext& ctx) const { + SG::ReadCondHandle<AthenaAttributeList> readHandle{m_bcidDataKey, ctx}; + return(**readHandle)["Beam1Bunches"].data<unsigned int>(); +} + +unsigned int +LHCDataTool::getBeam1Bunches(void) const { + const EventContext& ctx{Gaudi::Hive::currentContext()}; + return getBeam1Bunches(ctx); +} + +unsigned int +LHCDataTool::getBeam2Bunches(const EventContext& ctx) const { + SG::ReadCondHandle<AthenaAttributeList> readHandle{m_bcidDataKey, ctx}; + return(**readHandle)["Beam2Bunches"].data<unsigned int>(); +} + +unsigned int +LHCDataTool::getBeam2Bunches(void) const { + const EventContext& ctx{Gaudi::Hive::currentContext()}; + return getBeam2Bunches(ctx); +} + +unsigned int +LHCDataTool::getCollidingBunches(const EventContext& ctx) const { + SG::ReadCondHandle<AthenaAttributeList> readHandle{m_bcidDataKey, ctx}; + return(**readHandle)["CollidingBunches"].data<unsigned int>(); +} + +unsigned int +LHCDataTool::getCollidingBunches(void) const { + const EventContext& ctx{Gaudi::Hive::currentContext()}; + return getCollidingBunches(ctx); +} + + +//---------------------------------------------------------------------- +// This function unpacks the blob every time this is accesed +// Should probably cache this using a callback +std::vector<unsigned char> +LHCDataTool::getBCIDMasks(const EventContext& ctx) const { + + SG::ReadCondHandle<AthenaAttributeList> bcidHandle{m_bcidDataKey, ctx}; + const coral::Blob& blob = (**bcidHandle)["BCIDmasks"].data<coral::Blob>(); + const unsigned char* p = static_cast<const unsigned char*>(blob.startingAddress()); + + // Should always be 3564 BCIDs + if (blob.size() != 3564) { + ATH_MSG_WARNING("Found BCID blob with size " << blob.size() << "!"); + } + + std::vector<unsigned char> bcid_vector(3564); + + bool first = true; + for (int i=0; i<blob.size(); i++) { + // First BCID is 1, but this is stored at location i=1 + // So you can index this vector as bcid_vector[bcid_number] + bcid_vector[i] = *p++; + if (first && (bcid_vector[i] == 3)) { + first = false; + ATH_MSG_DEBUG("Found first colliding BCID at " << i); + } + } + + return bcid_vector; +} + +std::vector<unsigned char> +LHCDataTool::getBCIDMasks(void) const { + const EventContext& ctx{Gaudi::Hive::currentContext()}; + return getBCIDMasks(ctx); +} + + + diff --git a/LHCData/LHCDataTools/src/LHCDataTool.h b/LHCData/LHCDataTools/src/LHCDataTool.h new file mode 100644 index 0000000000000000000000000000000000000000..3acabfb7502ac6b33d5b6d8a918fe8be97582b74 --- /dev/null +++ b/LHCData/LHCDataTools/src/LHCDataTool.h @@ -0,0 +1,101 @@ +// -*- C++ -*- + +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS and CERN collaborations +*/ + +/** @file LHCDataTool.h Header file for LHCDataTool. + @author Eric Torrence, 20/04/22 +*/ + +// Multiple inclusion protection +#ifndef LHCDATA_TOOL +#define LHCDATA_TOOL + +// Include interface class +#include "AthenaBaseComps/AthAlgTool.h" +#include "LHCDataTools/ILHCDataTool.h" + +// Include Athena stuff +#include "AthenaPoolUtilities/CondAttrListCollection.h" +#include "StoreGate/ReadCondHandleKey.h" + +#include "GaudiKernel/ICondSvc.h" +#include "Gaudi/Property.h" + +// Include Gaudi classes +#include "GaudiKernel/EventContext.h" + +/** This class contains a Tool that reads Waveform range data and makes it available to + other algorithms. The current implementation reads the data from a COOL database. +*/ + +class LHCDataTool: public extends<AthAlgTool, ILHCDataTool> { + + public: + //----------Public Member Functions----------// + // Structors + LHCDataTool(const std::string& type, const std::string& name, const IInterface* parent); //!< Constructor + virtual ~LHCDataTool() = default; //!< Destructor + + // Standard Gaudi functions + virtual StatusCode initialize() override; //!< Gaudi initialiser + virtual StatusCode finalize() override; //!< Gaudi finaliser + + // Methods to return fill data + // Methods to return beam data + virtual int getFillNumber(const EventContext& ctx) const override; + virtual int getFillNumber(void) const override; + + virtual std::string getMachineMode(const EventContext& ctx) const override; + virtual std::string getMachineMode(void) const override; + + virtual std::string getBeamMode(const EventContext& ctx) const override; + virtual std::string getBeamMode(void) const override; + + virtual int getBeamType1(const EventContext& ctx) const override; + virtual int getBeamType1(void) const override; + + virtual int getBeamType2(const EventContext& ctx) const override; + virtual int getBeamType2(void) const override; + + virtual float getBetaStar(const EventContext& ctx) const override; + virtual float getBetaStar(void) const override; + + virtual float getCrossingAngle(const EventContext& ctx) const override; + virtual float getCrossingAngle(void) const override; + + virtual bool getStableBeams(const EventContext& ctx) const override; + virtual bool getStableBeams(void) const override; + + virtual std::string getInjectionScheme(const EventContext& ctx) const override; + virtual std::string getInjectionScheme(void) const override; + + // Methods to return BCID data + virtual unsigned int getBeam1Bunches(const EventContext& ctx) const override; + virtual unsigned int getBeam1Bunches(void) const override; + + virtual unsigned int getBeam2Bunches(const EventContext& ctx) const override; + virtual unsigned int getBeam2Bunches(void) const override; + + virtual unsigned int getCollidingBunches(const EventContext& ctx) const override; + virtual unsigned int getCollidingBunches(void) const override; + + // This returns a char for each BCID encoding beam1/beam2 + // A colliding BCID will have value 3 + // BCIDs always count starting at 1 + virtual std::vector<unsigned char> getBCIDMasks(const EventContext& ctx) const override; + virtual std::vector<unsigned char> getBCIDMasks(void) const override; + + private: + // Read Cond Handles + //SG::ReadCondHandleKey<AthenaAttributeList> m_fillDataKey{this, "FillDataKey", "/LHC/FillData", "Key of fill data folder"}; + SG::ReadCondHandleKey<AthenaAttributeList> m_beamDataKey{this, "BeamDataKey", "/LHC/BeamData", "Key of fill data folder"}; + SG::ReadCondHandleKey<AthenaAttributeList> m_bcidDataKey{this, "BcidDataKey", "/LHC/BCIDData", "Key of fill data folder"}; + + ServiceHandle<ICondSvc> m_condSvc{this, "CondSvc", "CondSvc"}; + +}; + +//---------------------------------------------------------------------- +#endif // LHCDATA_TOOL diff --git a/LHCData/LHCDataTools/src/components/LHCDataTools_entries.cxx b/LHCData/LHCDataTools/src/components/LHCDataTools_entries.cxx new file mode 100644 index 0000000000000000000000000000000000000000..1f44bf0909b4a2be2b03f8e276baab0c5ed58cf9 --- /dev/null +++ b/LHCData/LHCDataTools/src/components/LHCDataTools_entries.cxx @@ -0,0 +1,3 @@ +#include "../LHCDataTool.h" + +DECLARE_COMPONENT( LHCDataTool ) diff --git a/MagneticField/FaserBFieldData/share/FieldSimulation.py b/MagneticField/FaserBFieldData/share/FieldSimulation.py new file mode 100644 index 0000000000000000000000000000000000000000..e17f617bc727f42de17c5aada7addde94761ac7f --- /dev/null +++ b/MagneticField/FaserBFieldData/share/FieldSimulation.py @@ -0,0 +1,254 @@ +# Calculation of the magnetic field from first principles +# @author Dave Casper, Tobias Boeckh +# see also https://github.com/dwcasper/KalmanFilter/blob/master/Field/BField/__init__.py + + +from math import sin, cos, atan2, sqrt, pi +from auto_diff import true_np as np +from scipy.special import iv, kn +from scipy.integrate import quad + +junk = np.seterr() + +# Geometry description +rMin = 0.104 +rMax = rMin + 0.0825 +zMax = [1.5, 1.0, 1.0] +magnetZ = [-0.81232, 0.637726, 1.837726] +m0 = 1.00 # mag +sectorPhi = np.linspace(0, 2 * pi, 17, True) # central phi value for each sector +magPhi = 2 * sectorPhi # angle of the magnetization in each sector +phiConst = 4 * sqrt(2 - sqrt(2)) # numerical result of phiPrime integration on curved surface +rhoLimit = rMin / 100 # region to use linear approx for rho +proj = np.zeros(17) +magVector = {} + +for j in range(0, 16, True): + magLo = m0 * np.array([cos(magPhi[j]), sin(magPhi[j]), 0]) + magVector[j] = magLo + magHi = m0 * np.array([cos(magPhi[j + 1]), sin(magPhi[j + 1]), 0]) + phiHat = np.array([-sin(j * pi / 8 + pi / 16), cos(j * pi / 8 + pi / 16), 0]) + proj[j] = np.matmul((magLo - magHi), phiHat) + + +def Field(position): + # expects position in millimeters + return bFieldXYZ(position[0] / 1000, position[1] / 1000, position[2] / 1000) + + +# negative derivative (with respect to rho) of integrand over curved surface +def cylDrho(rho, phi, z, rhoPrime, L, k): + if rho < rhoPrime: + bessel_k = kn(1, k * rhoPrime) + if bessel_k == 0: + return 0 + return ( + -m0 * (phiConst / pi**2) * rhoPrime * (iv(0, k * rho) + iv(2, k * rho)) + * bessel_k * cos(k * z) * cos(phi) * sin(k * L / 2) + ) + + else: + bessel_k = kn(0, k * rho) + kn(2, k * rho) + if bessel_k == 0: + return 0 + return ( + -m0 * (phiConst / pi**2) * rhoPrime * iv(1, k * rhoPrime) + * bessel_k * cos(k * z) * cos(phi) * sin(k * L / 2) + ) + + +# negative derivative (with respect to phi) of integrand over curved surface, divided by rho +def cylDphi(rho, phi, z, rhoPrime, L, k): + if rho < rhoLimit: + bessel_k = kn(1, k * rhoPrime) + if bessel_k == 0: + return 0 + return ( + m0 * (phiConst / pi**2) * rhoPrime * bessel_k * cos(k * z) + * sin(k * L / 2) * sin(phi) + ) + elif rho < rhoPrime: + bessel_k = kn(1, k * rhoPrime) + if bessel_k == 0: + return 0 + return ( + m0 * (2 * phiConst / (k * pi**2)) * rhoPrime * iv(1, k * rho) + * bessel_k * cos(k * z) * sin(k * L / 2) * sin(phi) / rho + ) + else: + bessel_k = kn(1, k * rho) + if bessel_k == 0: + return 0 + return ( + m0 * (2 * phiConst / (k * pi**2)) * rhoPrime * iv(1, k * rhoPrime) + * bessel_k * cos(k * z) * sin(k * L / 2) * sin(phi) / rho + ) + + +# negative derivative (with respect to z) of integrand over curved surface; valid for rho < rhoPrime +def cylDz(rho, phi, z, rhoPrime, L, k): + if rho < rhoPrime: + bessel_k = kn(1, k * rhoPrime) + if bessel_k == 0: + return 0 + return ( + -m0 * (2 * phiConst / pi**2) * rhoPrime * iv(1, k * rho) + * bessel_k * sin(k * z) * sin(k * L / 2) * cos(phi) + ) + else: + bessel_k = kn(1, k * rho) + if bessel_k == 0: + return 0 + return ( + m0 * (2 * phiConst / pi**2) * rhoPrime * iv(1, k * rhoPrime) + * bessel_k * sin(k * z) * sin(k * L / 2) * cos(phi) + ) + + +# negative derivative (with respect to rho) of integrand over sector boundary surface +def planeDrho(rho, phi, z, j, L, rhoPrime): + phiPrime = j * pi / 8 + pi / 16 + aSq = rho**2 + rhoPrime**2 - 2 * rho * rhoPrime * cos(phi - phiPrime) + aSqMinus = aSq + (z - L / 2) ** 2 + aSqPlus = aSq + (z + L / 2) ** 2 + return ( + (proj[j] / (4 * pi)) * (rho - rhoPrime * cos(phi - phiPrime)) + * ( + 1 / ((sqrt(aSqPlus) + z + L / 2) * sqrt(aSqPlus)) + - 1 / ((sqrt(aSqMinus) + z - L / 2) * sqrt(aSqMinus)) + ) + ) + + +# negative derivative (with respect to phi) of integrand over sector boundary surface, divided by rho +def planeDphi(rho, phi, z, j, L, rhoPrime): + phiPrime = j * pi / 8 + pi / 16 + aSq = rho**2 + rhoPrime**2 - 2 * rho * rhoPrime * cos(phi - phiPrime) + aSqMinus = aSq + (z - L / 2) ** 2 + aSqPlus = aSq + (z + L / 2) ** 2 + return ( + (proj[j] / (4 * pi)) * rhoPrime + * ( + 1 / ((sqrt(aSqPlus) + z + L / 2) * sqrt(aSqPlus)) + - 1 / ((sqrt(aSqMinus) + z - L / 2) * sqrt(aSqMinus)) + ) + * sin(phi - phiPrime) + ) + + +# negative derivative (with respect to z) of integrand over sector boundary surface, divided by rho +def planeDz(rho, phi, z, j, L, rhoPrime): + phiPrime = j * pi / 8 + pi / 16 + aSq = rho**2 + rhoPrime**2 - 2 * rho * rhoPrime * cos(phi - phiPrime) + aSqMinus = aSq + (z - L / 2) ** 2 + aSqPlus = aSq + (z + L / 2) ** 2 + return (proj[j] / (4 * pi)) * (1 / sqrt(aSqPlus) - 1 / sqrt(aSqMinus)) + + +def field(rho, phi, z, L): + fieldCylRho = lambda k: -cylDrho(rho, phi, z, rMin, L, k) + cylDrho( + rho, phi, z, rMax, L, k + ) + fieldPlaneRho = lambda rhoPrime: sum( + list(map(lambda j: planeDrho(rho, phi, z, j, L, rhoPrime), range(16))) + ) + + fieldCylPhi = lambda k: -cylDphi(rho, phi, z, rMin, L, k) + cylDphi( + rho, phi, z, rMax, L, k + ) + fieldPlanePhi = lambda rhoPrime: sum( + list(map(lambda j: planeDphi(rho, phi, z, j, L, rhoPrime), range(16))) + ) + + fieldCylZ = lambda k: -cylDz(rho, phi, z, rMin, L, k) + cylDz( + rho, phi, z, rMax, L, k + ) + fieldPlaneZ = lambda rhoPrime: sum( + list(map(lambda j: planeDz(rho, phi, z, j, L, rhoPrime), range(16))) + ) + myLimit = 1000 + return np.array( + [ + -quad(fieldCylRho, 0, np.inf, limit=myLimit)[0] + + quad(fieldPlaneRho, rMin, rMax, limit=myLimit)[0], + -quad(fieldCylPhi, 0, np.inf, limit=myLimit)[0] + + quad(fieldPlanePhi, rMin, rMax, limit=myLimit)[0], + quad(fieldCylZ, 0, np.inf, limit=myLimit)[0] + + quad(fieldPlaneZ, rMin, rMax, limit=myLimit)[0], + ] + ) + + +def mField(rho, phi, z): + magnetization = np.zeros(3) + if phi < 0: + phi = phi + 2 * pi + for iz in range(3): + if ( + z < (magnetZ[iz] - zMax[iz] / 2) + or z > (magnetZ[iz] + zMax[iz] / 2) + or rho < rMin + or rho > rMax + ): + continue + j = (phi + pi / 16) // (pi / 8) + j = j % 16 + magnetization = magVector[j] # this is cartesian! + break + rhoUnit = np.array([cos(phi), sin(phi), 0]) + phiUnit = np.array([-sin(phi), cos(phi), 0]) + zUnit = np.array([0, 0, 1]) + return np.array( + [ + np.matmul(magnetization, rhoUnit), + np.matmul(magnetization, phiUnit), + np.matmul(magnetization, zUnit), + ] + ) + + +def mFieldXYZ(x, y, z): + rho = sqrt(x**2 + y**2) + if rho > 0: + phi = atan2(y, x) + else: + phi = 0 + + m = mField(rho, phi, z) + return np.array( + [m[0] * cos(phi) - m[1] * sin(phi), m[0] * sin(phi) + m[1] * cos(phi), m[2]] + ) + + +def bField(rho, phi, z): + return ( + hField(rho, phi, z - magnetZ[0], zMax[0]) + + hField(rho, phi, z - magnetZ[1], zMax[1]) + + hField(rho, phi, z - magnetZ[2], zMax[2]) + + mField(rho, phi, z) + ) + + +def bFieldXYZ(x, y, z): + return hFieldXYZ(x, y, z) + mFieldXYZ(x, y, z) + + +def hField(rho, phi, z): + return ( + field(rho, phi, z - magnetZ[0], zMax[0]) + + field(rho, phi, z - magnetZ[1], zMax[1]) + + field(rho, phi, z - magnetZ[2], zMax[2]) + ) + + +def hFieldXYZ(x, y, z): + rho = sqrt(x**2 + y**2) + if rho > 0: + phi = atan2(y, x) + else: + phi = 0 + + h = hField(rho, phi, z) + return np.array( + [h[0] * cos(phi) - h[1] * sin(phi), h[0] * sin(phi) + h[1] * cos(phi), h[2]] + ) diff --git a/PhysicsAnalysis/NeutrinoSearch/CMakeLists.txt b/PhysicsAnalysis/NeutrinoSearch/CMakeLists.txt index cff2ab8575553261c18eb0736c211528e44f22bb..29ea0c53b37e81e5cf4b4ec63e958ac0a344f299 100644 --- a/PhysicsAnalysis/NeutrinoSearch/CMakeLists.txt +++ b/PhysicsAnalysis/NeutrinoSearch/CMakeLists.txt @@ -5,7 +5,7 @@ atlas_add_component( src/NeutrinoSearchAlg.h src/NeutrinoSearchAlg.cxx src/component/NeutrinoSearch_entries.cxx - LINK_LIBRARIES AthenaBaseComps StoreGateLib xAODFaserWaveform ScintIdentifier FaserCaloIdentifier GeneratorObjects FaserActsGeometryLib TrackerSimEvent TrackerSimData TrackerIdentifier TrackerReadoutGeometry TrkTrack GeoPrimitives TrackerRIO_OnTrack + LINK_LIBRARIES AthenaBaseComps StoreGateLib xAODFaserWaveform ScintIdentifier ScintSimEvent FaserCaloIdentifier GeneratorObjects FaserActsGeometryLib TrackerSimEvent TrackerSimData TrackerIdentifier TrackerReadoutGeometry TrkTrack GeoPrimitives TrackerRIO_OnTrack ) atlas_install_python_modules(python/*.py) diff --git a/PhysicsAnalysis/NeutrinoSearch/python/FilterSearchConfig.py b/PhysicsAnalysis/NeutrinoSearch/python/FilterSearchConfig.py index 9b76c14b8b6682b6cfe77ed3331467d4f9737cfe..1bea526ebb4ba14c750d89a652ee6fbe166db355 100644 --- a/PhysicsAnalysis/NeutrinoSearch/python/FilterSearchConfig.py +++ b/PhysicsAnalysis/NeutrinoSearch/python/FilterSearchConfig.py @@ -482,7 +482,7 @@ if __name__ == "__main__": ] - ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-02" # Always needed; must match FaserVersionS + ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-03" # Always needed; must match FaserVersionS ConfigFlags.IOVDb.DatabaseInstance = "OFLP200" # Use MC conditions for now ConfigFlags.Input.ProjectName = "data21" # Needed to bypass autoconfig ConfigFlags.Input.isMC = False # Needed to bypass autoconfig diff --git a/PhysicsAnalysis/NeutrinoSearch/python/FlukaSearchConfig.py b/PhysicsAnalysis/NeutrinoSearch/python/FlukaSearchConfig.py index 4e196a3794670d241bf8a26b91d409d260ac193d..4e81f6bcf7ba871622430d5ae246045f9fc043f6 100644 --- a/PhysicsAnalysis/NeutrinoSearch/python/FlukaSearchConfig.py +++ b/PhysicsAnalysis/NeutrinoSearch/python/FlukaSearchConfig.py @@ -47,51 +47,52 @@ if __name__ == "__main__": # Configure ConfigFlags.Input.Files = [ - '/run/media/dcasper/Data/faser/fluka/210001/rec/r0008/FaserMC-MDC_Fluka_unit30_Nm_71m_m3750_v3-210001-00000-s0005-r0008-xAOD.root', - '/run/media/dcasper/Data/faser/fluka/210001/rec/r0008/FaserMC-MDC_Fluka_unit30_Nm_71m_m3750_v3-210001-00001-s0005-r0008-xAOD.root', - '/run/media/dcasper/Data/faser/fluka/210001/rec/r0008/FaserMC-MDC_Fluka_unit30_Nm_71m_m3750_v3-210001-00002-s0005-r0008-xAOD.root', - '/run/media/dcasper/Data/faser/fluka/210001/rec/r0008/FaserMC-MDC_Fluka_unit30_Nm_71m_m3750_v3-210001-00003-s0005-r0008-xAOD.root', - '/run/media/dcasper/Data/faser/fluka/210001/rec/r0008/FaserMC-MDC_Fluka_unit30_Nm_71m_m3750_v3-210001-00004-s0005-r0008-xAOD.root', - '/run/media/dcasper/Data/faser/fluka/210001/rec/r0008/FaserMC-MDC_Fluka_unit30_Nm_71m_m3750_v3-210001-00005-s0005-r0008-xAOD.root', - '/run/media/dcasper/Data/faser/fluka/210001/rec/r0008/FaserMC-MDC_Fluka_unit30_Nm_71m_m3750_v3-210001-00006-s0005-r0008-xAOD.root', - '/run/media/dcasper/Data/faser/fluka/210001/rec/r0008/FaserMC-MDC_Fluka_unit30_Nm_71m_m3750_v3-210001-00007-s0005-r0008-xAOD.root', - '/run/media/dcasper/Data/faser/fluka/210001/rec/r0008/FaserMC-MDC_Fluka_unit30_Nm_71m_m3750_v3-210001-00008-s0005-r0008-xAOD.root', - '/run/media/dcasper/Data/faser/fluka/210001/rec/r0008/FaserMC-MDC_Fluka_unit30_Nm_71m_m3750_v3-210001-00009-s0005-r0008-xAOD.root', - '/run/media/dcasper/Data/faser/fluka/210001/rec/r0008/FaserMC-MDC_Fluka_unit30_Nm_71m_m3750_v3-210001-00010-s0005-r0008-xAOD.root', - '/run/media/dcasper/Data/faser/fluka/210001/rec/r0008/FaserMC-MDC_Fluka_unit30_Nm_71m_m3750_v3-210001-00011-s0005-r0008-xAOD.root', - '/run/media/dcasper/Data/faser/fluka/210001/rec/r0008/FaserMC-MDC_Fluka_unit30_Nm_71m_m3750_v3-210001-00012-s0005-r0008-xAOD.root', - '/run/media/dcasper/Data/faser/fluka/210001/rec/r0008/FaserMC-MDC_Fluka_unit30_Nm_71m_m3750_v3-210001-00013-s0005-r0008-xAOD.root', - '/run/media/dcasper/Data/faser/fluka/210001/rec/r0008/FaserMC-MDC_Fluka_unit30_Nm_71m_m3750_v3-210001-00014-s0005-r0008-xAOD.root', - '/run/media/dcasper/Data/faser/fluka/210001/rec/r0008/FaserMC-MDC_Fluka_unit30_Nm_71m_m3750_v3-210001-00015-s0005-r0008-xAOD.root', - '/run/media/dcasper/Data/faser/fluka/210001/rec/r0008/FaserMC-MDC_Fluka_unit30_Nm_71m_m3750_v3-210001-00016-s0005-r0008-xAOD.root', - '/run/media/dcasper/Data/faser/fluka/210001/rec/r0008/FaserMC-MDC_Fluka_unit30_Nm_71m_m3750_v3-210001-00017-s0005-r0008-xAOD.root', - '/run/media/dcasper/Data/faser/fluka/210001/rec/r0008/FaserMC-MDC_Fluka_unit30_Nm_71m_m3750_v3-210001-00018-s0005-r0008-xAOD.root', - '/run/media/dcasper/Data/faser/fluka/210001/rec/r0008/FaserMC-MDC_Fluka_unit30_Nm_71m_m3750_v3-210001-00019-s0005-r0008-xAOD.root', - '/run/media/dcasper/Data/faser/fluka/210001/rec/r0008/FaserMC-MDC_Fluka_unit30_Nm_71m_m3750_v3-210001-00020-s0005-r0008-xAOD.root', - '/run/media/dcasper/Data/faser/fluka/210001/rec/r0008/FaserMC-MDC_Fluka_unit30_Nm_71m_m3750_v3-210001-00021-s0005-r0008-xAOD.root', - '/run/media/dcasper/Data/faser/fluka/210001/rec/r0008/FaserMC-MDC_Fluka_unit30_Nm_71m_m3750_v3-210001-00022-s0005-r0008-xAOD.root', - '/run/media/dcasper/Data/faser/fluka/210001/rec/r0008/FaserMC-MDC_Fluka_unit30_Nm_71m_m3750_v3-210001-00023-s0005-r0008-xAOD.root', - '/run/media/dcasper/Data/faser/fluka/210001/rec/r0008/FaserMC-MDC_Fluka_unit30_Nm_71m_m3750_v3-210001-00024-s0005-r0008-xAOD.root', - '/run/media/dcasper/Data/faser/fluka/210001/rec/r0008/FaserMC-MDC_Fluka_unit30_Nm_71m_m3750_v3-210001-00025-s0005-r0008-xAOD.root', - '/run/media/dcasper/Data/faser/fluka/210001/rec/r0008/FaserMC-MDC_Fluka_unit30_Nm_71m_m3750_v3-210001-00026-s0005-r0008-xAOD.root', - '/run/media/dcasper/Data/faser/fluka/210001/rec/r0008/FaserMC-MDC_Fluka_unit30_Nm_71m_m3750_v3-210001-00027-s0005-r0008-xAOD.root', - '/run/media/dcasper/Data/faser/fluka/210002/rec/r0008/FaserMC-MDC_Fluka_unit30_Pm_71m_m3750_v3-210002-00000-s0005-r0008-xAOD.root', - '/run/media/dcasper/Data/faser/fluka/210002/rec/r0008/FaserMC-MDC_Fluka_unit30_Pm_71m_m3750_v3-210002-00001-s0005-r0008-xAOD.root', - '/run/media/dcasper/Data/faser/fluka/210002/rec/r0008/FaserMC-MDC_Fluka_unit30_Pm_71m_m3750_v3-210002-00002-s0005-r0008-xAOD.root', - '/run/media/dcasper/Data/faser/fluka/210002/rec/r0008/FaserMC-MDC_Fluka_unit30_Pm_71m_m3750_v3-210002-00003-s0005-r0008-xAOD.root', - '/run/media/dcasper/Data/faser/fluka/210002/rec/r0008/FaserMC-MDC_Fluka_unit30_Pm_71m_m3750_v3-210002-00004-s0005-r0008-xAOD.root', - '/run/media/dcasper/Data/faser/fluka/210002/rec/r0008/FaserMC-MDC_Fluka_unit30_Pm_71m_m3750_v3-210002-00005-s0005-r0008-xAOD.root', - '/run/media/dcasper/Data/faser/fluka/210002/rec/r0008/FaserMC-MDC_Fluka_unit30_Pm_71m_m3750_v3-210002-00006-s0005-r0008-xAOD.root', - '/run/media/dcasper/Data/faser/fluka/210002/rec/r0008/FaserMC-MDC_Fluka_unit30_Pm_71m_m3750_v3-210002-00007-s0005-r0008-xAOD.root', - '/run/media/dcasper/Data/faser/fluka/210002/rec/r0008/FaserMC-MDC_Fluka_unit30_Pm_71m_m3750_v3-210002-00008-s0005-r0008-xAOD.root', - '/run/media/dcasper/Data/faser/fluka/210002/rec/r0008/FaserMC-MDC_Fluka_unit30_Pm_71m_m3750_v3-210002-00009-s0005-r0008-xAOD.root', - '/run/media/dcasper/Data/faser/fluka/210002/rec/r0008/FaserMC-MDC_Fluka_unit30_Pm_71m_m3750_v3-210002-00010-s0005-r0008-xAOD.root', - '/run/media/dcasper/Data/faser/fluka/210002/rec/r0008/FaserMC-MDC_Fluka_unit30_Pm_71m_m3750_v3-210002-00011-s0005-r0008-xAOD.root', - '/run/media/dcasper/Data/faser/fluka/210002/rec/r0008/FaserMC-MDC_Fluka_unit30_Pm_71m_m3750_v3-210002-00012-s0005-r0008-xAOD.root', - '/run/media/dcasper/Data/faser/fluka/210002/rec/r0008/FaserMC-MDC_Fluka_unit30_Pm_71m_m3750_v3-210002-00013-s0005-r0008-xAOD.root', - '/run/media/dcasper/Data/faser/fluka/210002/rec/r0008/FaserMC-MDC_Fluka_unit30_Pm_71m_m3750_v3-210002-00014-s0005-r0008-xAOD.root', - '/run/media/dcasper/Data/faser/fluka/210002/rec/r0008/FaserMC-MDC_Fluka_unit30_Pm_71m_m3750_v3-210002-00015-s0005-r0008-xAOD.root' + '/run/media/dcasper/Data/faser/fluka/210002/rec/r0009/./FaserMC-MDC_Fluka_unit30_Pm_71m_m3750_v3-210002-00011-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/fluka/210002/rec/r0009/./FaserMC-MDC_Fluka_unit30_Pm_71m_m3750_v3-210002-00003-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/fluka/210002/rec/r0009/./FaserMC-MDC_Fluka_unit30_Pm_71m_m3750_v3-210002-00001-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/fluka/210002/rec/r0009/./FaserMC-MDC_Fluka_unit30_Pm_71m_m3750_v3-210002-00015-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/fluka/210002/rec/r0009/./FaserMC-MDC_Fluka_unit30_Pm_71m_m3750_v3-210002-00010-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/fluka/210002/rec/r0009/./FaserMC-MDC_Fluka_unit30_Pm_71m_m3750_v3-210002-00014-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/fluka/210002/rec/r0009/./FaserMC-MDC_Fluka_unit30_Pm_71m_m3750_v3-210002-00009-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/fluka/210002/rec/r0009/./FaserMC-MDC_Fluka_unit30_Pm_71m_m3750_v3-210002-00000-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/fluka/210002/rec/r0009/./FaserMC-MDC_Fluka_unit30_Pm_71m_m3750_v3-210002-00008-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/fluka/210002/rec/r0009/./FaserMC-MDC_Fluka_unit30_Pm_71m_m3750_v3-210002-00012-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/fluka/210002/rec/r0009/./FaserMC-MDC_Fluka_unit30_Pm_71m_m3750_v3-210002-00002-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/fluka/210002/rec/r0009/./FaserMC-MDC_Fluka_unit30_Pm_71m_m3750_v3-210002-00004-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/fluka/210002/rec/r0009/./FaserMC-MDC_Fluka_unit30_Pm_71m_m3750_v3-210002-00013-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/fluka/210002/rec/r0009/./FaserMC-MDC_Fluka_unit30_Pm_71m_m3750_v3-210002-00007-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/fluka/210002/rec/r0009/./FaserMC-MDC_Fluka_unit30_Pm_71m_m3750_v3-210002-00005-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/fluka/210002/rec/r0009/./FaserMC-MDC_Fluka_unit30_Pm_71m_m3750_v3-210002-00006-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/fluka/210001/rec/r0009/./FaserMC-MDC_Fluka_unit30_Nm_71m_m3750_v3-210001-00017-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/fluka/210001/rec/r0009/./FaserMC-MDC_Fluka_unit30_Nm_71m_m3750_v3-210001-00020-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/fluka/210001/rec/r0009/./FaserMC-MDC_Fluka_unit30_Nm_71m_m3750_v3-210001-00010-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/fluka/210001/rec/r0009/./FaserMC-MDC_Fluka_unit30_Nm_71m_m3750_v3-210001-00012-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/fluka/210001/rec/r0009/./FaserMC-MDC_Fluka_unit30_Nm_71m_m3750_v3-210001-00001-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/fluka/210001/rec/r0009/./FaserMC-MDC_Fluka_unit30_Nm_71m_m3750_v3-210001-00018-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/fluka/210001/rec/r0009/./FaserMC-MDC_Fluka_unit30_Nm_71m_m3750_v3-210001-00004-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/fluka/210001/rec/r0009/./FaserMC-MDC_Fluka_unit30_Nm_71m_m3750_v3-210001-00019-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/fluka/210001/rec/r0009/./FaserMC-MDC_Fluka_unit30_Nm_71m_m3750_v3-210001-00007-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/fluka/210001/rec/r0009/./FaserMC-MDC_Fluka_unit30_Nm_71m_m3750_v3-210001-00003-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/fluka/210001/rec/r0009/./FaserMC-MDC_Fluka_unit30_Nm_71m_m3750_v3-210001-00008-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/fluka/210001/rec/r0009/./FaserMC-MDC_Fluka_unit30_Nm_71m_m3750_v3-210001-00005-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/fluka/210001/rec/r0009/./FaserMC-MDC_Fluka_unit30_Nm_71m_m3750_v3-210001-00022-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/fluka/210001/rec/r0009/./FaserMC-MDC_Fluka_unit30_Nm_71m_m3750_v3-210001-00011-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/fluka/210001/rec/r0009/./FaserMC-MDC_Fluka_unit30_Nm_71m_m3750_v3-210001-00006-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/fluka/210001/rec/r0009/./FaserMC-MDC_Fluka_unit30_Nm_71m_m3750_v3-210001-00013-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/fluka/210001/rec/r0009/./FaserMC-MDC_Fluka_unit30_Nm_71m_m3750_v3-210001-00021-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/fluka/210001/rec/r0009/./FaserMC-MDC_Fluka_unit30_Nm_71m_m3750_v3-210001-00015-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/fluka/210001/rec/r0009/./FaserMC-MDC_Fluka_unit30_Nm_71m_m3750_v3-210001-00026-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/fluka/210001/rec/r0009/./FaserMC-MDC_Fluka_unit30_Nm_71m_m3750_v3-210001-00027-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/fluka/210001/rec/r0009/./FaserMC-MDC_Fluka_unit30_Nm_71m_m3750_v3-210001-00014-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/fluka/210001/rec/r0009/./FaserMC-MDC_Fluka_unit30_Nm_71m_m3750_v3-210001-00024-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/fluka/210001/rec/r0009/./FaserMC-MDC_Fluka_unit30_Nm_71m_m3750_v3-210001-00000-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/fluka/210001/rec/r0009/./FaserMC-MDC_Fluka_unit30_Nm_71m_m3750_v3-210001-00009-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/fluka/210001/rec/r0009/./FaserMC-MDC_Fluka_unit30_Nm_71m_m3750_v3-210001-00025-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/fluka/210001/rec/r0009/./FaserMC-MDC_Fluka_unit30_Nm_71m_m3750_v3-210001-00016-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/fluka/210001/rec/r0009/./FaserMC-MDC_Fluka_unit30_Nm_71m_m3750_v3-210001-00023-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/fluka/210001/rec/r0009/./FaserMC-MDC_Fluka_unit30_Nm_71m_m3750_v3-210001-00002-s0007-r0009-xAOD.root' ] + # Update this for samples with new field map ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-02" # Always needed; must match FaserVersionS ConfigFlags.IOVDb.DatabaseInstance = "OFLP200" # Use MC conditions for now ConfigFlags.Input.ProjectName = "data21" # Needed to bypass autoconfig diff --git a/PhysicsAnalysis/NeutrinoSearch/python/GenieSearchConfig.py b/PhysicsAnalysis/NeutrinoSearch/python/GenieSearchConfig.py index a80de32bbc0643dbaca1ac12e28688535951b709..94d860f75196b82b1c5ca3cdd6b3c84e1e06f171 100644 --- a/PhysicsAnalysis/NeutrinoSearch/python/GenieSearchConfig.py +++ b/PhysicsAnalysis/NeutrinoSearch/python/GenieSearchConfig.py @@ -47,14 +47,27 @@ if __name__ == "__main__": # Configure ConfigFlags.Input.Files = [ - '/run/media/dcasper/Data/faser/genie/rec/FaserMC-MDC_Genie_all_150invfb_v1-200001-00000-00007-s0006-r0008-xAOD.root', - '/run/media/dcasper/Data/faser/genie/rec/FaserMC-MDC_Genie_all_150invfb_v1-200001-00008-00015-s0006-r0008-xAOD.root', - '/run/media/dcasper/Data/faser/genie/rec/FaserMC-MDC_Genie_all_150invfb_v1-200001-00016-00023-s0006-r0008-xAOD.root', - '/run/media/dcasper/Data/faser/genie/rec/FaserMC-MDC_Genie_all_150invfb_v1-200001-00024-00031-s0006-r0008-xAOD.root', - '/run/media/dcasper/Data/faser/genie/rec/FaserMC-MDC_Genie_all_150invfb_v1-200001-00032-00039-s0006-r0008-xAOD.root', - '/run/media/dcasper/Data/faser/genie/rec/FaserMC-MDC_Genie_all_150invfb_v1-200001-00040-00047-s0006-r0008-xAOD.root', - '/run/media/dcasper/Data/faser/genie/rec/FaserMC-MDC_Genie_all_150invfb_v1-200001-00048-00055-s0006-r0008-xAOD.root', - '/run/media/dcasper/Data/faser/genie/rec/FaserMC-MDC_Genie_all_150invfb_v1-200001-00056-00063-s0006-r0008-xAOD.root' + '/run/media/dcasper/Data/faser/genie/r0009/rec/./FaserMC-MDC_Genie_all_600fbInv_v1-200003-00040-00047-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/genie/r0009/rec/./FaserMC-MDC_Genie_all_600fbInv_v1-200003-00056-00063-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/genie/r0009/rec/./FaserMC-MDC_Genie_all_600fbInv_v1-200003-00120-00127-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/genie/r0009/rec/./FaserMC-MDC_Genie_all_600fbInv_v1-200003-00112-00119-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/genie/r0009/rec/./FaserMC-MDC_Genie_all_600fbInv_v1-200003-00000-00007-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/genie/r0009/rec/./FaserMC-MDC_Genie_all_600fbInv_v1-200003-00208-00210-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/genie/r0009/rec/./FaserMC-MDC_Genie_all_600fbInv_v1-200003-00200-00207-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/genie/r0009/rec/./FaserMC-MDC_Genie_all_600fbInv_v1-200003-00064-00071-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/genie/r0009/rec/./FaserMC-MDC_Genie_all_600fbInv_v1-200003-00080-00087-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/genie/r0009/rec/./FaserMC-MDC_Genie_all_600fbInv_v1-200003-00024-00031-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/genie/r0009/rec/./FaserMC-MDC_Genie_all_600fbInv_v1-200003-00072-00079-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/genie/r0009/rec/./FaserMC-MDC_Genie_all_600fbInv_v1-200003-00008-00015-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/genie/r0009/rec/./FaserMC-MDC_Genie_all_600fbInv_v1-200003-00176-00183-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/genie/r0009/rec/./FaserMC-MDC_Genie_all_600fbInv_v1-200003-00096-00103-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/genie/r0009/rec/./FaserMC-MDC_Genie_all_600fbInv_v1-200003-00104-00111-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/genie/r0009/rec/./FaserMC-MDC_Genie_all_600fbInv_v1-200003-00032-00039-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/genie/r0009/rec/./FaserMC-MDC_Genie_all_600fbInv_v1-200003-00048-00055-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/genie/r0009/rec/./FaserMC-MDC_Genie_all_600fbInv_v1-200003-00192-00199-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/genie/r0009/rec/./FaserMC-MDC_Genie_all_600fbInv_v1-200003-00088-00095-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/genie/r0009/rec/./FaserMC-MDC_Genie_all_600fbInv_v1-200003-00016-00023-s0007-r0009-xAOD.root', + '/run/media/dcasper/Data/faser/genie/r0009/rec/./FaserMC-MDC_Genie_all_600fbInv_v1-200003-00168-00175-s0007-r0009-xAOD.root' ] ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-02" # Always needed; must match FaserVersionS ConfigFlags.IOVDb.DatabaseInstance = "OFLP200" # Use MC conditions for now diff --git a/PhysicsAnalysis/NeutrinoSearch/src/NeutrinoSearchAlg.cxx b/PhysicsAnalysis/NeutrinoSearch/src/NeutrinoSearchAlg.cxx index e782dda9e3eb7d97da42edb1b5a79528268dac9f..e3d33d683e0b47d064216515cf83fb280cb9edd4 100644 --- a/PhysicsAnalysis/NeutrinoSearch/src/NeutrinoSearchAlg.cxx +++ b/PhysicsAnalysis/NeutrinoSearch/src/NeutrinoSearchAlg.cxx @@ -28,6 +28,8 @@ StatusCode NeutrinoSearchAlg::initialize() { ATH_CHECK(m_truthEventContainer.initialize()); ATH_CHECK(m_truthParticleContainer.initialize()); + ATH_CHECK( m_vetoNuHitKey.initialize() ); + ATH_CHECK(m_trackCollection.initialize()); ATH_CHECK(m_vetoNuContainer.initialize()); ATH_CHECK(m_vetoContainer.initialize()); @@ -46,6 +48,7 @@ StatusCode NeutrinoSearchAlg::initialize() ATH_CHECK(detStore()->retrieve(m_detMgr, "SCT")); ATH_CHECK(m_extrapolationTool.retrieve()); + ATH_CHECK(m_trackingGeometryTool.retrieve()); if (m_useFlukaWeights) { @@ -64,6 +67,9 @@ StatusCode NeutrinoSearchAlg::initialize() m_tree->Branch("run_number", &m_run_number, "run_number/I"); m_tree->Branch("event_number", &m_event_number, "event_number/I"); +// m_tree->Branch("VetoNuTruthX", &m_vetoNuHitsMeanX, "vetoNuTruthX/D"); +// m_tree->Branch("VetoNuTruthY", &m_vetoNuHitsMeanY, "vetoNuTruthY/D"); + m_tree->Branch("VetoNuPmt0", &m_vetoNu0, "vetoNu0/D"); m_tree->Branch("VetoNuPmt1", &m_vetoNu1, "vetoNu1/D"); @@ -106,9 +112,17 @@ StatusCode NeutrinoSearchAlg::initialize() m_tree->Branch("ndof", &m_ndof, "ndof/I"); m_tree->Branch("longTracks", &m_longTracks, "longTracks/I"); m_tree->Branch("pTruthLepton", &m_truthLeptonMomentum, "pTruthLepton/D"); + m_tree->Branch("xTruthLepton", &m_truthLeptonX, "xTruthLepton/D"); + m_tree->Branch("yTruthLepton", &m_truthLeptonY, "yTruthLepton/D"); m_tree->Branch("truthBarcode", &m_truthBarcode, "truthBarcode/I"); m_tree->Branch("truthPdg", &m_truthPdg, "truthPdg/I"); m_tree->Branch("CrossSection", &m_crossSection, "crossSection/D"); + m_tree->Branch("xVetoNu", &m_xVetoNu, "xVetoNu/D"); + m_tree->Branch("yVetoNu", &m_yVetoNu, "yVetoNu/D"); + m_tree->Branch("sxVetoNu", &m_sxVetoNu, "sxVetoNu/D"); + m_tree->Branch("syVetoNu", &m_syVetoNu, "syVetoNu/D"); + m_tree->Branch("thetaxVetoNu", &m_thetaxVetoNu, "thetaxVetoNu/D"); + m_tree->Branch("thetayVetoNu", &m_thetayVetoNu, "thetayVetoNu/D"); ATH_CHECK(histSvc()->regTree("/HIST2/tree", m_tree)); @@ -145,6 +159,23 @@ StatusCode NeutrinoSearchAlg::execute(const EventContext &ctx) const double flukaWeight = truthEventContainer->at(0)->weights()[0]; ATH_MSG_ALWAYS("Found fluka weight = " << flukaWeight); m_crossSection = m_baseEventCrossSection * flukaWeight; + + // // Find crossing position of VetoNu so we can check extrapolation + // SG::ReadHandle<ScintHitCollection> h_vetoNuHits {m_vetoNuHitKey, ctx}; + // if (h_vetoNuHits.isValid() && h_vetoNuHits->size()!=0){ + // double totalEnergyLoss {0.0}; + // for (const ScintHit& hit : *h_vetoNuHits) + // { + // m_vetoNuHitsMeanX += hit.energyLoss() * (hit.localStartPosition().x() + hit.localEndPosition().x()) / 2; + // m_vetoNuHitsMeanY += hit.energyLoss() * (hit.localStartPosition().y() + hit.localEndPosition().y()) / 2; + // totalEnergyLoss += hit.energyLoss(); + // } + // if (totalEnergyLoss > 0) + // { + // m_vetoNuHitsMeanX /= totalEnergyLoss; + // m_vetoNuHitsMeanY /= totalEnergyLoss; + // } + // } } else if (m_useGenieWeights) { @@ -166,8 +197,14 @@ StatusCode NeutrinoSearchAlg::execute(const EventContext &ctx) const if ( particle->absPdgId() == 11 || particle->absPdgId() == 13 || particle->absPdgId() == 15 ) { if (particle->status() == 1 && (particle->nParents() == 0 || particle->nParents() == 2) ) + { m_truthLeptonMomentum = particle->p4().P(); - + double deltaZ = m_zExtrapolate - particle->prodVtx()->z(); + double thetaX = particle->px()/particle->pz(); + double thetaY = particle->py()/particle->pz(); + m_truthLeptonX = particle->prodVtx()->x() + thetaX * deltaZ; + m_truthLeptonY = particle->prodVtx()->y() + thetaY * deltaZ; + } break; } } @@ -435,6 +472,7 @@ StatusCode NeutrinoSearchAlg::execute(const EventContext &ctx) const const Trk::TrackParameters* upstreamParameters {nullptr}; for (auto params : *(track->trackParameters())) { + if (params->position().z() < 0) continue; // Ignore IFT hits if (upstreamParameters == nullptr || params->position().z() < upstreamParameters->position().z()) upstreamParameters = params; } if (candidateParameters == nullptr || upstreamParameters->momentum().mag() > candidateParameters->momentum().mag()) @@ -457,98 +495,98 @@ StatusCode NeutrinoSearchAlg::execute(const EventContext &ctx) const if (cluster != nullptr) { // ATH_MSG_INFO("ClusterOnTrack is OK"); - cluster->dump(msg()); + // cluster->dump(msg()); // Hack to work around issue with cluster navigation - auto idRDO = cluster->identify(); + // auto idRDO = cluster->identify(); + + // if (simDataCollection->count(idRDO) > 0) + // { + // // ATH_MSG_INFO("rdo entry found"); + // const auto& simdata = simDataCollection->find(idRDO)->second; + // const auto& deposits = simdata.getdeposits(); + // //loop through deposits and record contributions + // HepMcParticleLink primary{}; + // for( const auto& depositPair : deposits) + // { + // // ATH_MSG_INFO("Deposit found"); + // float eDep = depositPair.second; + // int barcode = depositPair.first->barcode(); + // // if( depositPair.second > highestDep) + // // { + // // highestDep = depositPair.second; + // // barcode = depositPair.first->barcode(); + // // primary = depositPair.first; + // // depositPair.first->print(std::cout); + // // ATH_MSG_INFO("pdg id "<<depositPair.first->pdg_id()); + // // } + // if (truthMap.count(barcode) > 0) + // { + // truthMap[barcode] += eDep; + // } + // else + // { + // truthMap[barcode] = eDep; + // } + // } + // } + + + - if (simDataCollection->count(idRDO) > 0) - { - // ATH_MSG_INFO("rdo entry found"); - const auto& simdata = simDataCollection->find(idRDO)->second; - const auto& deposits = simdata.getdeposits(); - //loop through deposits and record contributions - HepMcParticleLink primary{}; - for( const auto& depositPair : deposits) + // const Tracker::FaserSCT_Cluster* origCluster = dynamic_cast<const Tracker::FaserSCT_Cluster*>(cluster->prepRawData()); + auto origCluster = cluster->prepRawData(); + if (origCluster != nullptr) { - // ATH_MSG_INFO("Deposit found"); - float eDep = depositPair.second; - int barcode = depositPair.first->barcode(); - // if( depositPair.second > highestDep) - // { - // highestDep = depositPair.second; - // barcode = depositPair.first->barcode(); - // primary = depositPair.first; - // depositPair.first->print(std::cout); - // ATH_MSG_INFO("pdg id "<<depositPair.first->pdg_id()); - // } - if (truthMap.count(barcode) > 0) + // ATH_MSG_INFO("Orig Cluster is OK"); + auto rdoList = origCluster->rdoList(); + for (auto idRDO : rdoList) { - truthMap[barcode] += eDep; - } - else - { - truthMap[barcode] = eDep; + // ATH_MSG_INFO("rdoList not empty"); + if (simDataCollection->count(idRDO) > 0) + { + // ATH_MSG_INFO("rdo entry found"); + const auto& simdata = simDataCollection->find(idRDO)->second; + const auto& deposits = simdata.getdeposits(); + //loop through deposits and record contributions + HepMcParticleLink primary{}; + for( const auto& depositPair : deposits) + { + // ATH_MSG_INFO("Deposit found"); + float eDep = depositPair.second; + int barcode = depositPair.first->barcode(); + // if( depositPair.second > highestDep) + // { + // highestDep = depositPair.second; + // barcode = depositPair.first->barcode(); + // primary = depositPair.first; + // depositPair.first->print(std::cout); + // ATH_MSG_INFO("pdg id "<<depositPair.first->pdg_id()); + // } + if (truthMap.count(barcode) > 0) + { + truthMap[barcode] += eDep; + } + else + { + truthMap[barcode] = eDep; + } + } + } } } - } - - - - - // // const Tracker::FaserSCT_Cluster* origCluster = dynamic_cast<const Tracker::FaserSCT_Cluster*>(cluster->prepRawData()); - // auto origCluster = cluster->prepRawData(); - // if (origCluster != nullptr) - // { - // ATH_MSG_INFO("Orig Cluster is OK"); - // auto rdoList = origCluster->rdoList(); - // for (auto idRDO : rdoList) - // { - // ATH_MSG_INFO("rdoList not empty"); - // if (simDataCollection->count(idRDO) > 0) - // { - // ATH_MSG_INFO("rdo entry found"); - // const auto& simdata = simDataCollection->find(idRDO)->second; - // const auto& deposits = simdata.getdeposits(); - // //loop through deposits and record contributions - // HepMcParticleLink primary{}; - // for( const auto& depositPair : deposits) - // { - // ATH_MSG_INFO("Deposit found"); - // float eDep = depositPair.second; - // int barcode = depositPair.first->barcode(); - // // if( depositPair.second > highestDep) - // // { - // // highestDep = depositPair.second; - // // barcode = depositPair.first->barcode(); - // // primary = depositPair.first; - // // depositPair.first->print(std::cout); - // // ATH_MSG_INFO("pdg id "<<depositPair.first->pdg_id()); - // // } - // if (truthMap.count(barcode) > 0) - // { - // truthMap[barcode] += eDep; - // } - // else - // { - // truthMap[barcode] = eDep; - // } - // } - // } - // } - // } } } std::vector<std::pair<int, float>> truth(truthMap.begin(), truthMap.end()); std::sort(truth.begin(), truth.end(), [](auto v1, auto v2) { return v1.second > v2.second; }); - if (truth.size()>0) ATH_MSG_ALWAYS("Selected track truth info:"); + // if (truth.size()>0) ATH_MSG_ALWAYS("Selected track truth info:"); for (auto v : truth) { auto truthParticle = (*(std::find_if(truthParticleContainer->cbegin(), truthParticleContainer->cend(), [v](const xAOD::TruthParticle* p){ return p->barcode() == v.first; }))); if (m_truthPdg == 0) m_truthPdg = truthParticle->pdgId(); if (m_truthBarcode == 0) m_truthBarcode = v.first; - ATH_MSG_ALWAYS("truth info: barcode = " << v.first << " ( " << truthParticle->p4().P()/1000 << " GeV/c, Id code = " << truthParticle->pdgId() << ") -> deposited energy: " << v.second/1000); + // ATH_MSG_ALWAYS("truth info: barcode = " << v.first << " ( " << truthParticle->p4().P()/1000 << " GeV/c, Id code = " << truthParticle->pdgId() << ") -> deposited energy: " << v.second/1000); } } @@ -562,6 +600,63 @@ StatusCode NeutrinoSearchAlg::execute(const EventContext &ctx) const m_pz = candidateParameters->momentum().z(); m_p = sqrt(m_px * m_px + m_py * m_py + m_pz * m_pz); m_charge = (int) candidateParameters->charge(); + + FaserActsGeometryContext faserGeometryContext = m_trackingGeometryTool->getNominalGeometryContext(); + auto gctx = faserGeometryContext.context(); + + + Amg::Vector3D position = candidateParameters->position(); + Amg::Vector3D momentum = candidateParameters->momentum(); + auto covariance = *candidateParameters->covariance(); + Acts::BoundVector params = Acts::BoundVector::Zero(); + params[Acts::eBoundLoc0] = -position.y(); + params[Acts::eBoundLoc1] = position.x(); + params[Acts::eBoundPhi] = momentum.phi(); + params[Acts::eBoundTheta] = momentum.theta(); + params[Acts::eBoundQOverP] = candidateParameters->charge() / momentum.mag(); + params[Acts::eBoundTime] = 0; + + using namespace Acts::UnitLiterals; + std::optional<AmgSymMatrix(6)> cov = std::nullopt; + Acts::BoundMatrix newCov = Acts::BoundMatrix::Zero(); + for (size_t i = 0; i < 5; i++) + for (size_t j = 0; j < 5; j++) + newCov(i, j) = covariance(i, j); + // ATH_MSG_ALWAYS("Covariance: " << covariance(1,1) << " newCov: " << newCov(1,1)); + // Convert the covariance matrix from GeV + for(int i=0; i < newCov.rows(); i++){ + newCov(i, 4) = newCov(i, 4)/1_MeV; + } + for(int i=0; i < newCov.cols(); i++){ + newCov(4, i) = newCov(4, i)/1_MeV; + } + cov = std::optional<AmgSymMatrix(6)>(newCov); + // ATH_MSG_ALWAYS("cov: " << cov.value()(1,1)); + auto startSurface = Acts::Surface::makeShared<Acts::PlaneSurface>(Acts::Vector3(0, 0, position.z()), Acts::Vector3(0, 0, 1)); + Acts::BoundTrackParameters startParameters(std::move(startSurface), params, candidateParameters->charge(), cov); + auto targetSurface_VetoNu = Acts::Surface::makeShared<Acts::PlaneSurface>(Acts::Vector3(0, 0, m_zExtrapolate), Acts::Vector3(0, 0, 1)); // -3112 mm is z position of VetoNu planes touching + std::unique_ptr<const Acts::BoundTrackParameters> targetParameters_VetoNu =m_extrapolationTool->propagate(ctx, startParameters, *targetSurface_VetoNu, Acts::backward); + if (targetParameters_VetoNu != nullptr) + { + auto targetPosition_VetoNu = targetParameters_VetoNu->position(gctx); + auto targetMomentum_VetoNu = targetParameters_VetoNu->momentum(); + // Acts::BoundSymMatrix targetCovariance_VetoNu { targetParameters_VetoNu->covariance() }; + m_xVetoNu = targetPosition_VetoNu.x(); + m_yVetoNu = targetPosition_VetoNu.y(); + if (targetParameters_VetoNu->covariance().has_value()) + { + auto targetCovariance_VetoNu = targetParameters_VetoNu->covariance().value() ; + m_sxVetoNu = sqrt(targetCovariance_VetoNu(Acts::eBoundLoc0, Acts::eBoundLoc0)); + m_syVetoNu = sqrt(targetCovariance_VetoNu(Acts::eBoundLoc1, Acts::eBoundLoc1)); + } + m_thetaxVetoNu = atan(targetMomentum_VetoNu[0]/targetMomentum_VetoNu[2]); + m_thetayVetoNu = atan(targetMomentum_VetoNu[1]/targetMomentum_VetoNu[2]); + ATH_MSG_INFO("vetoNu good targetParameters xV,yV = (" << m_xVetoNu << ", " << m_yVetoNu << ")"); + } + else + { + ATH_MSG_INFO("vetoNu null targetParameters with p = " << momentum.mag() << ", theta = " << momentum.theta() << ", x,y = (" << position.x() << ", " << position.y() << ")"); + } } // Here we apply the signal selection @@ -571,7 +666,18 @@ StatusCode NeutrinoSearchAlg::execute(const EventContext &ctx) const m_preshower0 == 0 || m_preshower1 == 0 || // m_ecalTotal == 0 || candidateParameters == nullptr) - return StatusCode::SUCCESS; + { + // if (m_longTracks > 0) + // { + // ATH_MSG_ALWAYS(m_vetoUpstream); + // ATH_MSG_ALWAYS(m_vetoDownstream); + // ATH_MSG_ALWAYS(m_triggerTotal); + // ATH_MSG_ALWAYS(m_preshower0); + // ATH_MSG_ALWAYS(m_preshower1); + // ATH_MSG_ALWAYS((candidateParameters == nullptr ? "Null" : "Not Null")); + // } + return StatusCode::SUCCESS; + } m_tree->Fill(); @@ -595,6 +701,8 @@ NeutrinoSearchAlg::clearTree() const { m_run_number = 0; m_event_number = 0; +// m_vetoNuHitsMeanX = 0; +// m_vetoNuHitsMeanY = 0; m_vetoNu0 = 0; m_vetoNu1 = 0; m_veto00 = 0; @@ -631,7 +739,15 @@ NeutrinoSearchAlg::clearTree() const m_y = 0; m_z = 0; m_longTracks = 0; + m_truthLeptonX = 0; + m_truthLeptonY = 0; m_truthLeptonMomentum = 0; m_truthBarcode = 0; m_truthPdg = 0; + m_xVetoNu = 0; + m_yVetoNu = 0; + m_sxVetoNu = 0; + m_syVetoNu = 0; + m_thetaxVetoNu = 0; + m_thetayVetoNu = 0; } \ No newline at end of file diff --git a/PhysicsAnalysis/NeutrinoSearch/src/NeutrinoSearchAlg.h b/PhysicsAnalysis/NeutrinoSearch/src/NeutrinoSearchAlg.h index d1732eb1238a15bb7b2fb397869b3c4486aa50b3..4c8ca653e2b7832dac95645135a10c83c57a846a 100644 --- a/PhysicsAnalysis/NeutrinoSearch/src/NeutrinoSearchAlg.h +++ b/PhysicsAnalysis/NeutrinoSearch/src/NeutrinoSearchAlg.h @@ -8,10 +8,11 @@ #include "xAODFaserWaveform/WaveformHit.h" #include "xAODTruth/TruthEventContainer.h" #include "xAODTruth/TruthParticleContainer.h" +#include "ScintSimEvent/ScintHitCollection.h" #include "TrackerPrepRawData/FaserSCT_ClusterContainer.h" #include "TrackerSimData/TrackerSimDataCollection.h" #include "FaserActsGeometryInterfaces/IFaserActsExtrapolationTool.h" - +#include "FaserActsGeometryInterfaces/IFaserActsTrackingGeometryTool.h" class TTree; class FaserSCT_ID; @@ -44,6 +45,7 @@ private: SG::ReadHandleKey<xAOD::TruthEventContainer> m_truthEventContainer { this, "EventContainer", "TruthEvents", "Truth event container name." }; SG::ReadHandleKey<xAOD::TruthParticleContainer> m_truthParticleContainer { this, "ParticleContainer", "TruthParticles", "Truth particle container name." }; SG::ReadHandleKey<TrackerSimDataCollection> m_simDataCollection {this, "TrackerSimDataCollection", "SCT_SDO_Map"}; + SG::ReadHandleKey<ScintHitCollection> m_vetoNuHitKey { this, "VetoNuHitCollection", "VetoNuHits" }; SG::ReadHandleKey<TrackCollection> m_trackCollection { this, "TrackCollection", "CKFTrackCollection", "Input track collection name" }; SG::ReadHandleKey<xAOD::WaveformHitContainer> m_vetoNuContainer { this, "VetoNuContainer", "VetoNuWaveformHits", "VetoNu hit container name" }; @@ -54,6 +56,7 @@ private: SG::ReadHandleKey<Tracker::FaserSCT_ClusterContainer> m_clusterContainer { this, "ClusterContainer", "SCT_ClusterContainer", "Tracker cluster container name" }; ToolHandle<IFaserActsExtrapolationTool> m_extrapolationTool { this, "ExtrapolationTool", "FaserActsExtrapolationTool" }; + ToolHandle<IFaserActsTrackingGeometryTool> m_trackingGeometryTool {this, "TrackingGeometryTool", "FaserActsTrackingGeometryTool"}; const TrackerDD::SCT_DetectorManager* m_detMgr {nullptr}; const FaserSCT_ID* m_sctHelper; @@ -75,7 +78,8 @@ private: BooleanProperty m_useGenieWeights { this, "UseGenieWeights", false, "Flag to weight events according to Genie luminosity" }; IntegerProperty m_flukaCollisions { this, "FlukaCollisions", 137130000, "Number of proton-proton collisions in FLUKA sample." }; DoubleProperty m_flukaCrossSection { this, "FlukaCrossSection", 80.0, "Fluka p-p inelastic cross-section in millibarns." }; - DoubleProperty m_genieLuminosity { this, "GenieLuminosity", 150.0, "Genie luminosity in inverse fb." }; + DoubleProperty m_genieLuminosity { this, "GenieLuminosity", 600.0, "Genie luminosity in inverse fb." }; + DoubleProperty m_zExtrapolate { this, "ZExtrapolationPlane", -3112.0, "Plane to extrapolate tracks for VetoNu" }; // BooleanProperty m_enforceBlinding { this, "EnforceBlinding", true, "Ignore data events with no VetoNu signals." }; const bool m_enforceBlinding {true}; @@ -111,6 +115,9 @@ private: mutable int m_station2Clusters; mutable int m_station3Clusters; + // mutable double m_vetoNuHitsMeanX; + // mutable double m_vetoNuHitsMeanY; + mutable double m_x; mutable double m_y; mutable double m_z; @@ -123,10 +130,17 @@ private: mutable int m_ndof; mutable int m_longTracks; mutable double m_truthLeptonMomentum; + mutable double m_truthLeptonX; + mutable double m_truthLeptonY; mutable int m_truthBarcode; mutable int m_truthPdg; mutable double m_crossSection; - + mutable double m_xVetoNu; + mutable double m_yVetoNu; + mutable double m_sxVetoNu; + mutable double m_syVetoNu; + mutable double m_thetaxVetoNu; + mutable double m_thetayVetoNu; }; inline const ServiceHandle <ITHistSvc> &NeutrinoSearchAlg::histSvc() const { diff --git a/PhysicsAnalysis/NtupleDumper/CMakeLists.txt b/PhysicsAnalysis/NtupleDumper/CMakeLists.txt index 944ed9689053915dd526251fabf1c5b1af5dfa4e..b81b98183b68fc67cf0df4592c7f1cad6917e6f4 100644 --- a/PhysicsAnalysis/NtupleDumper/CMakeLists.txt +++ b/PhysicsAnalysis/NtupleDumper/CMakeLists.txt @@ -5,7 +5,7 @@ atlas_add_component( src/NtupleDumperAlg.h src/NtupleDumperAlg.cxx src/component/NtupleDumper_entries.cxx - LINK_LIBRARIES AthenaBaseComps StoreGateLib xAODFaserWaveform xAODFaserTrigger ScintIdentifier FaserCaloIdentifier GeneratorObjects FaserActsGeometryLib TrackerSimEvent TrackerSimData TrackerIdentifier TrackerReadoutGeometry TrkTrack GeoPrimitives TrackerRIO_OnTrack TrackerSpacePoint + LINK_LIBRARIES AthenaBaseComps StoreGateLib xAODFaserWaveform xAODFaserTrigger ScintIdentifier FaserCaloIdentifier GeneratorObjects FaserActsGeometryLib TrackerSimEvent TrackerSimData TrackerIdentifier TrackerReadoutGeometry TrkTrack GeoPrimitives TrackerRIO_OnTrack TrackerSpacePoint FaserActsKalmanFilterLib ) atlas_install_python_modules(python/*.py) diff --git a/PhysicsAnalysis/NtupleDumper/src/NtupleDumperAlg.cxx b/PhysicsAnalysis/NtupleDumper/src/NtupleDumperAlg.cxx index d1a07f428c73dfb7d6c7f1bf69ab20b73f12a196..587a894b905e3e75e9e8c5cf708fc72b49c7c046 100644 --- a/PhysicsAnalysis/NtupleDumper/src/NtupleDumperAlg.cxx +++ b/PhysicsAnalysis/NtupleDumper/src/NtupleDumperAlg.cxx @@ -16,6 +16,9 @@ #include "xAODTruth/TruthParticle.h" #include <cmath> #include <TH1F.h> +#include <numeric> + +constexpr float NaN = std::numeric_limits<double>::quiet_NaN(); NtupleDumperAlg::NtupleDumperAlg(const std::string &name, @@ -70,7 +73,7 @@ void NtupleDumperAlg::FillWaveBranches(const xAOD::WaveformHitContainer &wave) c } } -StatusCode NtupleDumperAlg::initialize() +StatusCode NtupleDumperAlg::initialize() { ATH_CHECK(m_truthEventContainer.initialize()); ATH_CHECK(m_truthParticleContainer.initialize()); @@ -85,6 +88,7 @@ StatusCode NtupleDumperAlg::initialize() ATH_CHECK(m_simDataCollection.initialize()); ATH_CHECK(m_FaserTriggerData.initialize()); ATH_CHECK(m_ClockWaveformContainer.initialize()); + ATH_CHECK(m_siHitCollectionKey.initialize()); ATH_CHECK(detStore()->retrieve(m_sctHelper, "FaserSCT_ID")); ATH_CHECK(detStore()->retrieve(m_vetoNuHelper, "VetoNuID")); @@ -96,6 +100,8 @@ StatusCode NtupleDumperAlg::initialize() ATH_CHECK(detStore()->retrieve(m_detMgr, "SCT")); ATH_CHECK(m_extrapolationTool.retrieve()); ATH_CHECK(m_trackingGeometryTool.retrieve()); + ATH_CHECK(m_trackTruthMatchingTool.retrieve()); + ATH_CHECK(m_fiducialParticleTool.retrieve()); ATH_CHECK(m_spacePointContainerKey.initialize()); @@ -220,6 +226,41 @@ StatusCode NtupleDumperAlg::initialize() m_tree->Branch("Track_ThetaX_atCalo", &m_thetaxCalo); m_tree->Branch("Track_ThetaY_atCalo", &m_thetayCalo); + m_tree->Branch("t_pdg", &m_t_pdg); + m_tree->Branch("t_barcode", &m_t_barcode); + m_tree->Branch("t_truthHitRatio", &m_t_truthHitRatio); + m_tree->Branch("t_prodVtx_x", &m_t_prodVtx_x); + m_tree->Branch("t_prodVtx_y", &m_t_prodVtx_y); + m_tree->Branch("t_prodVtx_z", &m_t_prodVtx_z); + m_tree->Branch("t_decayVtx_x", &m_t_decayVtx_x); + m_tree->Branch("t_decayVtx_y", &m_t_decayVtx_y); + m_tree->Branch("t_decayVtx_z", &m_t_decayVtx_z); + m_tree->Branch("t_px", &m_t_px); + m_tree->Branch("t_py", &m_t_py); + m_tree->Branch("t_pz", &m_t_pz); + m_tree->Branch("t_theta", &m_t_theta); + m_tree->Branch("t_phi", &m_t_phi); + m_tree->Branch("t_p", &m_t_p); + m_tree->Branch("t_pT", &m_t_pT); + m_tree->Branch("t_eta", &m_t_eta); + m_tree->Branch("t_st0_x", &m_t_st_x[0]); + m_tree->Branch("t_st0_y", &m_t_st_y[0]); + m_tree->Branch("t_st0_z", &m_t_st_z[0]); + m_tree->Branch("t_st1_x", &m_t_st_x[1]); + m_tree->Branch("t_st1_y", &m_t_st_y[1]); + m_tree->Branch("t_st1_z", &m_t_st_z[1]); + m_tree->Branch("t_st2_x", &m_t_st_x[2]); + m_tree->Branch("t_st2_y", &m_t_st_y[2]); + m_tree->Branch("t_st2_z", &m_t_st_z[2]); + m_tree->Branch("t_st3_x", &m_t_st_x[3]); + m_tree->Branch("t_st3_y", &m_t_st_y[3]); + m_tree->Branch("t_st3_z", &m_t_st_z[3]); + m_tree->Branch("isFiducial", &m_isFiducial); + + m_tree->Branch("truthParticleBarcode", &m_truthParticleBarcode); + m_tree->Branch("truthParticleMatchedTracks", &m_truthParticleMatchedTracks); + m_tree->Branch("truthParticleIsFiducial", &m_truthParticleIsFiducial); + m_tree->Branch("pTruthLepton", &m_truthLeptonMomentum, "pTruthLepton/D"); m_tree->Branch("truthBarcode", &m_truthBarcode, "truthBarcode/I"); m_tree->Branch("truthPdg", &m_truthPdg, "truthPdg/I"); @@ -273,7 +314,7 @@ StatusCode NtupleDumperAlg::initialize() } -StatusCode NtupleDumperAlg::execute(const EventContext &ctx) const +StatusCode NtupleDumperAlg::execute(const EventContext &ctx) const { clearTree(); @@ -339,7 +380,7 @@ StatusCode NtupleDumperAlg::execute(const EventContext &ctx) const return StatusCode::SUCCESS; // finished with this event - } else if ( ((m_tap&8)==0) && (((m_tap&4)==0)||((m_tap&2)==0)) && (((m_tap&4)==0)||((m_tap&1)==0)) && (((m_tap&2)==0)||((m_tap&1)==0)) ) { // don't process events that don't trigger coincidence triggers: 1=calo, 2=veotnu|neto1|preshower, 4=TimingLayer, 8=(VetoNu|Veto2)&Preshower + } else if ( ((m_tap&8)==0) && (((m_tap&4)==0)||((m_tap&2)==0)) && (((m_tap&4)==0)||((m_tap&1)==0)) && (((m_tap&2)==0)||((m_tap&1)==0)) ) { // don't process events that don't trigger coincidence triggers: 1=calo, 2=veotnu|neto1|preshower, 4=TimingLayer, 8=(VetoNu|Veto2)&Preshower return StatusCode::SUCCESS; } m_tbp=triggerData->tbp(); @@ -420,7 +461,7 @@ StatusCode NtupleDumperAlg::execute(const EventContext &ctx) const FillWaveBranches(*triggerContainer); FillWaveBranches(*preshowerContainer); FillWaveBranches(*ecalContainer); - + m_calo_total=m_wave_charge[0]+m_wave_charge[1]+m_wave_charge[2]+m_wave_charge[3]; m_calo_rawtotal=m_wave_raw_charge[0]+m_wave_raw_charge[1]+m_wave_raw_charge[2]+m_wave_raw_charge[3]; @@ -430,13 +471,13 @@ StatusCode NtupleDumperAlg::execute(const EventContext &ctx) const m_Calo1_Edep = (m_wave_charge[1] / 24.333) * m_MIP_sim_Edep_calo; m_Calo2_Edep = (m_wave_charge[2] / 24.409) * m_MIP_sim_Edep_calo; m_Calo3_Edep = (m_wave_charge[3] / 25.555) * m_MIP_sim_Edep_calo; - } else if (m_CaloConfig == "Low_gain") { // assume low gain calo + } else if (m_CaloConfig == "Low_gain") { // assume low gain calo m_Calo0_Edep = (m_wave_charge[0] / 0.7909) * m_MIP_sim_Edep_calo; m_Calo1_Edep = (m_wave_charge[1] / 0.8197) * m_MIP_sim_Edep_calo; m_Calo2_Edep = (m_wave_charge[2] / 0.8256) * m_MIP_sim_Edep_calo; m_Calo3_Edep = (m_wave_charge[3] / 0.8821) * m_MIP_sim_Edep_calo; } else { - ATH_MSG_WARNING("Run config is neither High_gain nor Low_gain, it is " << m_CaloConfig << ", calo calibration will be zero"); + ATH_MSG_WARNING("Run config is neither High_gain nor Low_gain, it is " << m_CaloConfig << ", calo calibration will be zero"); } m_Calo_Total_Edep = m_Calo0_Edep + m_Calo1_Edep + m_Calo2_Edep + m_Calo3_Edep; @@ -517,6 +558,16 @@ StatusCode NtupleDumperAlg::execute(const EventContext &ctx) const m_trackseg_pz.push_back(SegMomentum.z()); } + std::map<int, size_t> truthParticleCount {}; + if (!realData) { + SG::ReadHandle<xAOD::TruthParticleContainer> truthParticleContainer { m_truthParticleContainer, ctx }; + ATH_CHECK(truthParticleContainer.isValid() && truthParticleContainer->size() > 0); + for (const xAOD::TruthParticle *tp : *truthParticleContainer) { + if (tp->p4().P() > m_minMomentum) + truthParticleCount[tp->barcode()] = 0; + } + } + SG::ReadHandle<TrackCollection> trackCollection {m_trackCollection, ctx}; ATH_CHECK(trackCollection.isValid()); const Trk::TrackParameters* candidateParameters {nullptr}; @@ -580,6 +631,56 @@ StatusCode NtupleDumperAlg::execute(const EventContext &ctx) const m_pzdown.push_back(candidateDownParameters->momentum().z()); m_pdown.push_back(sqrt( pow(candidateDownParameters->momentum().x(),2) + pow(candidateDownParameters->momentum().y(),2) + pow(candidateDownParameters->momentum().z(),2) )); + if (!realData) { + auto [truthParticle, hitCount] = m_trackTruthMatchingTool->getTruthParticle(track); + if (truthParticle != nullptr) { + if (truthParticleCount.count(truthParticle->barcode()) > 0) + truthParticleCount[truthParticle->barcode()] += 1; + m_t_pdg.push_back(truthParticle->pdgId()); + m_t_barcode.push_back(truthParticle->barcode()); + // the track fit eats up 5 degrees of freedom, thus the number of hits on track is m_DoF + 5 + m_t_truthHitRatio.push_back(hitCount / (m_DoF.back() + 5)); + m_isFiducial.push_back(m_fiducialParticleTool->isFiducial(truthParticle->barcode())); + auto positions = m_fiducialParticleTool->getTruthPositions(truthParticle->barcode()); + for (int station = 0; station < 4; ++station) { + m_t_st_x[station].push_back(positions[station].x()); + m_t_st_y[station].push_back(positions[station].y()); + m_t_st_z[station].push_back(positions[station].z()); + } + if (truthParticle->hasProdVtx()) { + m_t_prodVtx_x.push_back(truthParticle->prodVtx()->x()); + m_t_prodVtx_y.push_back(truthParticle->prodVtx()->y()); + m_t_prodVtx_z.push_back(truthParticle->prodVtx()->z()); + } else { + m_t_prodVtx_x.push_back(NaN); + m_t_prodVtx_y.push_back(NaN); + m_t_prodVtx_z.push_back(NaN); + } + if (truthParticle->hasDecayVtx()) { + m_t_decayVtx_x.push_back(truthParticle->decayVtx()->x()); + m_t_decayVtx_y.push_back(truthParticle->decayVtx()->y()); + m_t_decayVtx_z.push_back(truthParticle->decayVtx()->z()); + } else { + m_t_decayVtx_x.push_back(NaN); + m_t_decayVtx_y.push_back(NaN); + m_t_decayVtx_z.push_back(NaN); + } + m_t_px.push_back(truthParticle->px()); + m_t_py.push_back(truthParticle->py()); + m_t_pz.push_back(truthParticle->pz()); + m_t_theta.push_back(truthParticle->p4().Theta()); + m_t_phi.push_back(truthParticle->p4().Phi()); + m_t_p.push_back(truthParticle->p4().P()); + m_t_pT.push_back(truthParticle->p4().Pt()); + m_t_eta.push_back(truthParticle->p4().Eta()); + } else { + setNaN(); + } + } else { + ATH_MSG_WARNING("Can not find truthParticle."); + setNaN(); + } + // fill extrapolation vectors with filler values that get changed iif the track extrapolation succeeds m_xVetoNu.push_back(-10000); m_yVetoNu.push_back(-10000); @@ -676,7 +777,7 @@ StatusCode NtupleDumperAlg::execute(const EventContext &ctx) const ATH_MSG_INFO("Trig null targetParameters"); } - } + } // extrapolate track from tracking station 3 if (stationMap.count(3) > 0) { // extrapolation crashes if the track does not end in the Station 3, as it is too far away to extrapolate @@ -735,6 +836,14 @@ StatusCode NtupleDumperAlg::execute(const EventContext &ctx) const m_longTracks++; } + if (!realData) { + for (auto &tp : truthParticleCount) { + m_truthParticleBarcode.push_back(tp.first); + m_truthParticleMatchedTracks.push_back(tp.second); + m_truthParticleIsFiducial.push_back(m_fiducialParticleTool->isFiducial(tp.first)); + } + } + /* // Here we apply the signal selection // Very simple/unrealistic to start @@ -751,7 +860,7 @@ StatusCode NtupleDumperAlg::execute(const EventContext &ctx) const } -StatusCode NtupleDumperAlg::finalize() +StatusCode NtupleDumperAlg::finalize() { return StatusCode::SUCCESS; } @@ -843,7 +952,7 @@ NtupleDumperAlg::clearTree() const m_charge.clear(); m_nLayers.clear(); m_longTracks = 0; - + m_nHit0.clear(); m_nHit1.clear(); m_nHit2.clear(); @@ -884,7 +993,60 @@ NtupleDumperAlg::clearTree() const m_thetaxCalo.clear(); m_thetayCalo.clear(); + m_t_pdg.clear(); + m_t_barcode.clear(); + m_t_truthHitRatio.clear(); + m_t_prodVtx_x.clear(); + m_t_prodVtx_y.clear(); + m_t_prodVtx_z.clear(); + m_t_decayVtx_x.clear(); + m_t_decayVtx_y.clear(); + m_t_decayVtx_z.clear(); + m_t_px.clear(); + m_t_py.clear(); + m_t_pz.clear(); + m_t_theta.clear(); + m_t_phi.clear(); + m_t_p.clear(); + m_t_pT.clear(); + m_t_eta.clear(); + m_isFiducial.clear(); + for (int station = 0; station < 4; ++station) { + m_t_st_x[station].clear(); + m_t_st_y[station].clear(); + m_t_st_z[station].clear(); + } + m_truthParticleBarcode.clear(); + m_truthParticleMatchedTracks.clear(); + m_truthParticleIsFiducial.clear(); + m_truthLeptonMomentum = 0; m_truthBarcode = 0; m_truthPdg = 0; } + +void NtupleDumperAlg::setNaN() const { + m_t_pdg.push_back(0); + m_t_barcode.push_back(-1); + m_t_truthHitRatio.push_back(NaN); + m_t_prodVtx_x.push_back(NaN); + m_t_prodVtx_y.push_back(NaN); + m_t_prodVtx_z.push_back(NaN); + m_t_decayVtx_x.push_back(NaN); + m_t_decayVtx_y.push_back(NaN); + m_t_decayVtx_z.push_back(NaN); + m_t_px.push_back(NaN); + m_t_py.push_back(NaN); + m_t_pz.push_back(NaN); + m_t_theta.push_back(NaN); + m_t_phi.push_back(NaN); + m_t_p.push_back(NaN); + m_t_pT.push_back(NaN); + m_t_eta.push_back(NaN); + for (int station = 0; station < 4; ++station) { + m_t_st_x[station].push_back(NaN); + m_t_st_y[station].push_back(NaN); + m_t_st_z[station].push_back(NaN); + } + m_isFiducial.push_back(false); +} \ No newline at end of file diff --git a/PhysicsAnalysis/NtupleDumper/src/NtupleDumperAlg.h b/PhysicsAnalysis/NtupleDumper/src/NtupleDumperAlg.h index 1b26caadeb7290c34a199ef0e941f9203b600bba..fb805829e264d1d52a9e797306b7857592b1c977 100644 --- a/PhysicsAnalysis/NtupleDumper/src/NtupleDumperAlg.h +++ b/PhysicsAnalysis/NtupleDumper/src/NtupleDumperAlg.h @@ -15,6 +15,9 @@ #include "TrackerSimData/TrackerSimDataCollection.h" #include "FaserActsGeometryInterfaces/IFaserActsExtrapolationTool.h" #include "FaserActsGeometryInterfaces/IFaserActsTrackingGeometryTool.h" +#include "FaserActsKalmanFilter/IFiducialParticleTool.h" +#include "FaserActsKalmanFilter/ITrackTruthMatchingTool.h" +#include "TrackerSimEvent/FaserSiHitCollection.h" #include <vector> @@ -44,6 +47,7 @@ private: bool waveformHitOK(const xAOD::WaveformHit* hit) const; void clearTree() const; + void setNaN() const; void addBranch(const std::string &name,float* var); void addBranch(const std::string &name,unsigned int* var); void addWaveBranches(const std::string &name, int nchannels, int first); @@ -64,11 +68,14 @@ private: SG::ReadHandleKey<xAOD::WaveformHitContainer> m_ecalContainer { this, "EcalContainer", "CaloWaveformHits", "Ecal hit container name" }; SG::ReadHandleKey<Tracker::FaserSCT_ClusterContainer> m_clusterContainer { this, "ClusterContainer", "SCT_ClusterContainer", "Tracker cluster container name" }; SG::ReadHandleKey<FaserSCT_SpacePointContainer> m_spacePointContainerKey { this, "SpacePoints", "SCT_SpacePointContainer", "space point container"}; + SG::ReadHandleKey<FaserSiHitCollection> m_siHitCollectionKey{this, "FaserSiHitCollection", "SCT_Hits"}; SG::ReadHandleKey<xAOD::FaserTriggerData> m_FaserTriggerData { this, "FaserTriggerDataKey", "FaserTriggerData", "ReadHandleKey for xAOD::FaserTriggerData"}; SG::ReadHandleKey<xAOD::WaveformClock> m_ClockWaveformContainer { this, "WaveformClockKey", "WaveformClock", "ReadHandleKey for ClockWaveforms Container"}; ToolHandle<IFaserActsExtrapolationTool> m_extrapolationTool { this, "ExtrapolationTool", "FaserActsExtrapolationTool" }; ToolHandle<IFaserActsTrackingGeometryTool> m_trackingGeometryTool {this, "TrackingGeometryTool", "FaserActsTrackingGeometryTool"}; + ToolHandle<ITrackTruthMatchingTool> m_trackTruthMatchingTool {this, "TrackTruthMatchingTool", "TrackTruthMatchingTool"}; + ToolHandle<IFiducialParticleTool> m_fiducialParticleTool {this, "FiducialParticleTool", "FiducialParticleTool"}; const TrackerDD::SCT_DetectorManager* m_detMgr {nullptr}; @@ -86,6 +93,7 @@ private: IntegerProperty m_flukaCollisions { this, "FlukaCollisions", 137130000, "Number of proton-proton collisions in FLUKA sample." }; DoubleProperty m_flukaCrossSection { this, "FlukaCrossSection", 80.0, "Fluka p-p inelastic cross-section in millibarns." }; DoubleProperty m_genieLuminosity { this, "GenieLuminosity", 150.0, "Genie luminosity in inverse fb." }; + DoubleProperty m_minMomentum { this, "MinMomentum", 50000.0, "Write out all truth particles with a momentum larger MinMomentum"}; double m_baseEventCrossSection {1.0}; const double kfemtoBarnsPerMilliBarn {1.0e12}; @@ -203,6 +211,32 @@ private: mutable std::vector<double> m_thetaxCalo; mutable std::vector<double> m_thetayCalo; + mutable std::vector<int> m_t_pdg; // pdg code of the truth matched particle + mutable std::vector<int> m_t_barcode; // barcode of the truth matched particle + mutable std::vector<double> m_t_truthHitRatio; // ratio of hits on track matched to the truth particle over all hits on track + mutable std::vector<double> m_t_prodVtx_x; // x component of the production vertex in mm + mutable std::vector<double> m_t_prodVtx_y; // y component of the production vertex in mm + mutable std::vector<double> m_t_prodVtx_z; // z component of the production vertex in mm + mutable std::vector<double> m_t_decayVtx_x; // x component of the decay vertex in mm + mutable std::vector<double> m_t_decayVtx_y; // y component of the decay vertex in mm + mutable std::vector<double> m_t_decayVtx_z; // z component of the decay vertex in mm + mutable std::vector<double> m_t_px; // truth momentum px in MeV + mutable std::vector<double> m_t_py; // truth momentum py in MeV + mutable std::vector<double> m_t_pz; // truth momentum pz in MeV + mutable std::vector<double> m_t_theta; // angle of truth particle with respsect to the beam axis in rad, theta = arctan(sqrt(px * px + py * py) / pz) + mutable std::vector<double> m_t_phi; // polar angle of truth particle in rad, phi = arctan(py / px) + mutable std::vector<double> m_t_p; // truth momentum p in MeV + mutable std::vector<double> m_t_pT; // transverse truth momentum pT in MeV + mutable std::vector<double> m_t_eta; // eta of truth particle + mutable std::array<std::vector<double>, 4> m_t_st_x; // vector of the x components of the simulated hits of the truth particle for each station + mutable std::array<std::vector<double>, 4> m_t_st_y; // vector of the y components of the simulated hits of the truth particle for each station + mutable std::array<std::vector<double>, 4> m_t_st_z; // vector of the z components of the simulated hits of the truth particle for each station + mutable std::vector<bool> m_isFiducial; // track is fiducial if there are simulated hits for stations 1 - 3 and the distance from the center is smaller than 100 mm + + mutable std::vector<int> m_truthParticleBarcode; // vector of barcodes of all truth particles with a momentum larger 50 GeV + mutable std::vector<int> m_truthParticleMatchedTracks; // vector of number of tracks to which a truth particle is matched to + mutable std::vector<bool> m_truthParticleIsFiducial; // vector of boolean showing whether a truth particle is fiducial + mutable double m_truthLeptonMomentum; mutable int m_truthBarcode; mutable int m_truthPdg; diff --git a/README.md b/README.md index 2d7e57abb75b58112939efb7b2726607bcfb6ec3..bcd917f069ec308e9657f013a9398dba24285145 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,8 @@ When compiling, CERN IT recommends using condor to submit batch jobs. The basics ** `ConfigFlags.GeoModel.FaserVersion = "FASERNU-03"` and `ConfigFlags.IOVDb.GlobalTag = OFLCOND-FASER-02` enables the full FaserNu (IFT + emulsion) setup +** `ConfigFlags.GeoModel.FaserVersion = "FASERNU-03"` and `ConfigFlags.IOVDb.GlobalTag = OFLCOND-FASER-03` enables the full FaserNu (IFT + emulsion) setup with updated (10Nov22) magnetic field map + ** `ConfigFlags.GeoModel.FaserVersion = "FASER-TB00"` and `ConfigFlags.IOVDb.GlobalTag = OFLCOND-FASER-TB00` enables the 2021 Test-beam setup. * The command `source /cvmfs/sft.cern.ch/lcg/releases/LCG_101_ATLAS_6/sqlite/3320300/x86_64-centos7-gcc11-opt/sqlite-env.sh` may be necessary to avoid errors when generating a database diff --git a/Simulation/G4Faser/G4FaserAlg/CMakeLists.txt b/Simulation/G4Faser/G4FaserAlg/CMakeLists.txt index 35042d814e913677a0ddf4d643e792a75b362f2d..979897a94c4b476433d0ef3fe2ceeb31105f9ef5 100644 --- a/Simulation/G4Faser/G4FaserAlg/CMakeLists.txt +++ b/Simulation/G4Faser/G4FaserAlg/CMakeLists.txt @@ -36,6 +36,11 @@ atlas_add_test( G4FaserAlgConfig_TestFaserNu PROPERTIES TIMEOUT 300 PROPERTIES WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) +atlas_add_test( G4FaserAlgConfig_TestFaserNu_NewField + SCRIPT python ${CMAKE_CURRENT_SOURCE_DIR}/test/G4FaserAlgConfigNew_Test.py GeoModel.FaserVersion="'FASERNU-03'" IOVDb.GlobalTag="'OFLCOND-FASER-03'" Output.HITSFileName='faserNu.HITS.pool.root' + PROPERTIES TIMEOUT 300 + PROPERTIES WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) + atlas_add_test( G4FaserAlgConfig_TestTestbeam SCRIPT python ${CMAKE_CURRENT_SOURCE_DIR}/test/G4FaserAlgConfigNew_Test.py GeoModel.FaserVersion="'FASER-TB00'" IOVDb.GlobalTag="'OFLCOND-FASER-TB00'" Output.HITSFileName='tb.HITS.pool.root' PROPERTIES TIMEOUT 300 diff --git a/Simulation/G4Faser/G4FaserAlg/test/G4FaserAlgConfigNew_Test.py b/Simulation/G4Faser/G4FaserAlg/test/G4FaserAlgConfigNew_Test.py index 998b40c286837a3436e6fc714f4977b355ccdd9d..d7ea3c3ab921b57e3df3c5c4be56c102f873c8f7 100755 --- a/Simulation/G4Faser/G4FaserAlg/test/G4FaserAlgConfigNew_Test.py +++ b/Simulation/G4Faser/G4FaserAlg/test/G4FaserAlgConfigNew_Test.py @@ -49,7 +49,7 @@ if __name__ == '__main__': ConfigFlags.addFlag("Sim.Beam.yshift", 0) ConfigFlags.GeoModel.FaserVersion = "FASERNU-03" # Geometry set-up - ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-02" # Conditions set-up + ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-03" # Conditions set-up ConfigFlags.addFlag("Input.InitialTimeStamp", 0) # To avoid autoconfig ConfigFlags.GeoModel.Align.Dynamic = False # diff --git a/Tracker/TrackerConditions/FaserSCT_ConditionsData/README.md b/Tracker/TrackerConditions/FaserSCT_ConditionsData/README.md new file mode 100644 index 0000000000000000000000000000000000000000..8025a4b1d3244a86163371a4fae298a2108d47ef --- /dev/null +++ b/Tracker/TrackerConditions/FaserSCT_ConditionsData/README.md @@ -0,0 +1,33 @@ +# FaserSCT_ConditionsData + +For more information on conditions in general, see [[https://twiki.cern.ch/twiki/bin/view/FASER/OfflineDatabases][OfflineDatabases]]. + +## Creating databases + +The scripts +``` +data/SCT_Conditions.py +data/BField_DataConditions.py +``` +were used to create the intial databases for MC (OFLP200) and data (CONDBR3). + +## Updating field map + +The following was used to update the magnetic field map on 10 Nov. 22: +``` +cp /cvmfs/faser.cern.ch/repo/sw/database/DBRelease/current/sqlite200/ALLP200.db . + +# This creates new field and scale entries with tag OFLCOND-FASER-03 in mysqlite.db +BField_Conditions_Update03.py + +# Now we need to merge this into the existing DB +AtlCoolCopy "sqlite://;schema=mysqlite.db;dbname=OFLP200" "sqlite://;schema=ALLP200.db;dbname=OFLP200" +AtlCoolCopy "sqlite://;schema=mysqlite.db;dbname=CONDBR3" "sqlite://;schema=ALLP200.db;dbname=CONDBR3" + +# For the MC instance, we also need to associate the existing /SCT and /Tracker tags +AtlCoolConsole.py "sqlite://;schema=ALLP200.db;dbname=OFLP200" +settag /SCT SCT-02 OFLCOND-FASER-03 +settag /Tracker TRACKER-02 OFLCOND-FASER-03 +``` + +After installing the new tags in ALLP200.db, we can test this locally by copying it to the data/sqlite200 subdirectory of the run directory, and eventually install it on cvmfs. diff --git a/Tracker/TrackerConditions/FaserSCT_ConditionsData/data/BField_Conditions_Update03.py b/Tracker/TrackerConditions/FaserSCT_ConditionsData/data/BField_Conditions_Update03.py new file mode 100755 index 0000000000000000000000000000000000000000..8a99a5fba6709ab66c42587507657cb67802030c --- /dev/null +++ b/Tracker/TrackerConditions/FaserSCT_ConditionsData/data/BField_Conditions_Update03.py @@ -0,0 +1,158 @@ +#!/bin/env python + +# This script was used to add a new tag for the BField to both +# the real data (CONDBR3) and MC (OFLP200) instances. +# This writes out to mysqlite.db which then needs to be merged +# with the production database using: +# AtlCoolCopy "sqlite://;schema=mysqlite.db;dbname=CONDBR3" "sqlite://;schema=ALLP200.db;dbname=CONDBR3" + +description = '<timeStamp>run-lumi</timeStamp><addrHeader><address_header clid="1238547719" service_type="71" /></addrHeader><typeName>CondAttrListCollection</typeName>' + +descriptionDCS = '<timeStamp>time</timeStamp><addrHeader><address_header service_type="71" clid="1238547719" /></addrHeader><typeName>CondAttrListCollection</typeName><cache>600</cache>' + +descriptionAlign = '<timeStamp>run-lumi</timeStamp><addrHeader><address_header service_type="256" clid="1170039409" /></addrHeader><typeName>AlignableTransformContainer</typeName>' + +import sys +from PyCool import cool, coral +from CoolConvUtilities.AtlCoolLib import forceOpen + +print('generating new field database') + +dbSvc = cool.DatabaseSvcFactory.databaseService() +connectString = 'sqlite://;schema=mysqlite.db;dbname=CONDBR3' + +# This should open or create as needed +try: + print(f'forceOpen({connectString})') + db = forceOpen( connectString ) +except Exception as e: + print(e) + print('Problem opening DB!') + sys.exit(1) + +# Hierarchy of new tag is: +# OFLCOND-FASER-02 : GLOBAL-03 : GLOBAL-BField-03 : GLOBAL-BField-Maps-03 + +# Create new tag +glob = db.createFolderSet("/GLOBAL") +glob_bfield = db.createFolderSet("/GLOBAL/BField") + +glob_bfield.createTagRelation("GLOBAL-03", "GLOBAL-BField-03") +glob.createTagRelation("OFLCOND-FASER-03", "GLOBAL-03") + +print("Created tag GLOBAL-BField-03 and associated to OFLCOND-FASER-03") + +mapSpec = cool.RecordSpecification() +mapSpec.extend( 'FieldType', cool.StorageType.String4k ) +mapSpec.extend( 'MapFileName', cool.StorageType.String4k ) + +mapFolderSpec = cool.FolderSpecification(cool.FolderVersioning.MULTI_VERSION, mapSpec) +mapFolder = db.createFolder('/GLOBAL/BField/Maps', mapFolderSpec, descriptionDCS, True ) + +# New entry +mapRecord = cool.Record(mapSpec) +mapRecord['FieldType'] = "GlobalMap" +mapRecord['MapFileName'] = "file:MagneticFieldMaps/FaserFieldTable_v2.root" + +mapFolder.storeObject( cool.ValidityKeyMin, cool.ValidityKeyMax, mapRecord, 1, "GLOBAL-BField-Maps-03", True ) +mapFolder.createTagRelation("GLOBAL-BField-03", "GLOBAL-BField-Maps-03") + +print("Created new entry in /GLOBAL/BField/Maps with tag GLOBAL-BField-Maps-03") + +# Also update the scale (since it sits in the same tag area) +scaleSpec = cool.RecordSpecification() +scaleSpec.extend( 'value', cool.StorageType.Float ) + +scaleRecord = cool.Record(scaleSpec) +scaleRecord['value'] = 1.0 + +scaleFolderSpec = cool.FolderSpecification(cool.FolderVersioning.MULTI_VERSION, scaleSpec) +scaleFolder = db.createFolder('/GLOBAL/BField/Scales', scaleFolderSpec, descriptionDCS, True ) + +# Channel names don't seem to be handled properly by Athena +scaleFolder.createChannel( 1, "Dipole_Scale" ) + +scaleFolder.storeObject( cool.ValidityKeyMin, cool.ValidityKeyMax, scaleRecord, 1, "GLOBAL-BField-Scale-03", True ) +scaleFolder.createTagRelation("GLOBAL-BField-03", "GLOBAL-BField-Scale-03") + +print("Created new entry in /GLOBAL/BField/Maps with tag GLOBAL-BField-Scale-03") + +# These are the only tags in the CONDBR3 instance, so we are done + +db.closeDatabase() + +# Now do it again for the MC instance + +connectString = 'sqlite://;schema=mysqlite.db;dbname=OFLP200' + +# This should open or create as needed +try: + print(f'forceOpen({connectString})') + db = forceOpen( connectString ) +except Exception as e: + print(e) + print('Problem opening DB!') + sys.exit(1) + +# Create new tag +glob = db.createFolderSet("/GLOBAL") +glob_bfield = db.createFolderSet("/GLOBAL/BField") + +glob_bfield.createTagRelation("GLOBAL-03", "GLOBAL-BField-03") +glob.createTagRelation("OFLCOND-FASER-03", "GLOBAL-03") + +print("Created tag GLOBAL-BField-03 and associated to OFLCOND-FASER-03") + +mapSpec = cool.RecordSpecification() +mapSpec.extend( 'FieldType', cool.StorageType.String4k ) +mapSpec.extend( 'MapFileName', cool.StorageType.String4k ) + +mapFolderSpec = cool.FolderSpecification(cool.FolderVersioning.MULTI_VERSION, mapSpec) +mapFolder = db.createFolder('/GLOBAL/BField/Maps', mapFolderSpec, descriptionDCS, True ) + +# New entry +mapRecord = cool.Record(mapSpec) +mapRecord['FieldType'] = "GlobalMap" +mapRecord['MapFileName'] = "file:MagneticFieldMaps/FaserFieldTable_v2.root" + +mapFolder.storeObject( cool.ValidityKeyMin, cool.ValidityKeyMax, mapRecord, 1, "GLOBAL-BField-Maps-03", True ) +mapFolder.createTagRelation("GLOBAL-BField-03", "GLOBAL-BField-Maps-03") + +print("Created new entry in /GLOBAL/BField/Maps with tag GLOBAL-BField-Maps-03") + +# Also update the scale (since it sits in the same tag area) +scaleSpec = cool.RecordSpecification() +scaleSpec.extend( 'value', cool.StorageType.Float ) + +scaleRecord = cool.Record(scaleSpec) +scaleRecord['value'] = 1.0 + +scaleFolderSpec = cool.FolderSpecification(cool.FolderVersioning.MULTI_VERSION, scaleSpec) +scaleFolder = db.createFolder('/GLOBAL/BField/Scales', scaleFolderSpec, descriptionDCS, True ) + +# Channel names don't seem to be handled properly by Athena +scaleFolder.createChannel( 1, "Dipole_Scale" ) + +scaleFolder.storeObject( cool.ValidityKeyMin, cool.ValidityKeyMax, scaleRecord, 1, "GLOBAL-BField-Scale-03", True ) +scaleFolder.createTagRelation("GLOBAL-BField-03", "GLOBAL-BField-Scale-03") + +print("Created new entry in /GLOBAL/BField/Maps with tag GLOBAL-BField-Scale-03") + +# Also make associations to /SCT and /TRACKER tags +#sct = db.createFolderSet("/SCT") +#sct.createTagRelation("OFLCOND-FASER-03", "SCT-02") +#tracker = db.createFolderSet("/Tracker") +#tracker.createTagRelation("OFLCOND-FASER-03", "TRACKER-02") +#print("Associated old tags for /SCT and /Tracker to OFLCOND-FASER-03") + +# This doesn't work. +# Instead, we need to go into AtlCoolConsole.py and +# set the association there. +# +# settag /SCT SCT-02 OFLCOND-FASER-03 +# settag /Tracker TRACKER-02 OFLCOND-FASER-03 +# +# Check that this worked: +# tracetags / OFLCOND-FASER-03 + +db.closeDatabase() diff --git a/Tracker/TrackerConditions/FaserSCT_ConditionsData/data/BField_DataConditions.py b/Tracker/TrackerConditions/FaserSCT_ConditionsData/data/BField_DataConditions.py index 94846ee80dedb41dbc2354a6662873203aad9cb6..9fb21099b9dbeeb97f8632dc5a9e64919e40e3a1 100755 --- a/Tracker/TrackerConditions/FaserSCT_ConditionsData/data/BField_DataConditions.py +++ b/Tracker/TrackerConditions/FaserSCT_ConditionsData/data/BField_DataConditions.py @@ -3,6 +3,10 @@ # Use this to add a field map to the CONDBR3 database for real data # Copied the result from the OFLP200 DB # Note that the testbeam turns off the field by setting scale = 0 + +# This file creates the DB from scratch +# To add new tags, look at BField_Conditions_Update03.py + description = '<timeStamp>run-lumi</timeStamp><addrHeader><address_header clid="1238547719" service_type="71" /></addrHeader><typeName>CondAttrListCollection</typeName>' descriptionDCS = '<timeStamp>time</timeStamp><addrHeader><address_header service_type="71" clid="1238547719" /></addrHeader><typeName>CondAttrListCollection</typeName><cache>600</cache>' @@ -11,7 +15,7 @@ descriptionAlign = '<timeStamp>run-lumi</timeStamp><addrHeader><address_header s import sys from PyCool import cool, coral -from CoolConvUtilities.AtlCoolLib import indirectOpen +from CoolConvUtilities.AtlCoolLib import forceOpen dbSvc = cool.DatabaseSvcFactory.databaseService() connectString = 'sqlite://;schema=ALLP200.db;dbname=CONDBR3' @@ -20,8 +24,9 @@ print('generating field database') #dbSvc.dropDatabase( connectString ) try: # Open existing instead? - print('Try indirectOpen') - db = indirectOpen( connectString, readOnly=False ) + # This actually should open or create as needed + print(f'Try forceOpen({connectString})') + db = forceOpen( connectString ) except Exception as e: print(e) print('Problem opening DB, create instead') @@ -36,6 +41,9 @@ glob.createTagRelation("OFLCOND-FASER-01", "GLOBAL-01") glob_bfield.createTagRelation("GLOBAL-02", "GLOBAL-BField-02") glob.createTagRelation("OFLCOND-FASER-02", "GLOBAL-02") +glob_bfield.createTagRelation("GLOBAL-03", "GLOBAL-BField-03") +glob.createTagRelation("OFLCOND-FASER-03", "GLOBAL-03") + glob_bfield.createTagRelation("GLOBAL-TB00", "GLOBAL-BField-TB00") glob.createTagRelation("OFLCOND-FASER-TB00", "GLOBAL-TB00") @@ -43,13 +51,13 @@ mapSpec = cool.RecordSpecification() mapSpec.extend( 'FieldType', cool.StorageType.String4k ) mapSpec.extend( 'MapFileName', cool.StorageType.String4k ) -mapRecord = cool.Record(mapSpec) -mapRecord['FieldType'] = "GlobalMap" -mapRecord['MapFileName'] = "file:MagneticFieldMaps/FaserFieldTable.root" - mapFolderSpec = cool.FolderSpecification(cool.FolderVersioning.MULTI_VERSION, mapSpec) mapFolder = db.createFolder('/GLOBAL/BField/Maps', mapFolderSpec, descriptionDCS, True ) +mapRecord = cool.Record(mapSpec) +mapRecord['FieldType'] = "GlobalMap" +mapRecord['MapFileName'] = "file:MagneticFieldMaps/FaserFieldTable_v101.root" + mapFolder.storeObject( cool.ValidityKeyMin, cool.ValidityKeyMax, mapRecord, 1, "GLOBAL-BField-Maps-01", True ) mapFolder.createTagRelation("GLOBAL-BField-01", "GLOBAL-BField-Maps-01") @@ -59,6 +67,12 @@ mapFolder.createTagRelation("GLOBAL-BField-02", "GLOBAL-BField-Maps-02") mapFolder.storeObject( cool.ValidityKeyMin, cool.ValidityKeyMax, mapRecord, 1, "GLOBAL-BField-Maps-TB00", True ) mapFolder.createTagRelation("GLOBAL-BField-TB00", "GLOBAL-BField-Maps-TB00") +# New record +mapRecord['MapFileName'] = "file:MagneticFieldMaps/FaserFieldTable_v2.root" + +mapFolder.storeObject( cool.ValidityKeyMin, cool.ValidityKeyMax, mapRecord, 1, "GLOBAL-BField-Maps-03", True ) +mapFolder.createTagRelation("GLOBAL-BField-03", "GLOBAL-BField-Maps-03") + scaleSpec = cool.RecordSpecification() scaleSpec.extend( 'value', cool.StorageType.Float ) diff --git a/Tracker/TrackerRecAlgs/NoisyStripFinder/share/NoisyStripFinderJob.py b/Tracker/TrackerRecAlgs/NoisyStripFinder/share/NoisyStripFinderJob.py index b6dc5c514d05c558310bf1108e505deca1e8098c..e8c304455b27156d4c0b8983b9c04cd61367b2ce 100755 --- a/Tracker/TrackerRecAlgs/NoisyStripFinder/share/NoisyStripFinderJob.py +++ b/Tracker/TrackerRecAlgs/NoisyStripFinder/share/NoisyStripFinderJob.py @@ -39,7 +39,7 @@ for filename in args.file: filelist.append(filename) ConfigFlags.Input.Files = args.file -ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-02" +ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-03" #ConfigFlags.IOVDb.DatabaseInstance = "OFLP200" ConfigFlags.IOVDb.DatabaseInstance = "CONDBR3" ConfigFlags.Input.ProjectName = "data22" diff --git a/Tracker/TrackerRecAlgs/NoisyStripFinder/share/submitNoisyStripJobs.py b/Tracker/TrackerRecAlgs/NoisyStripFinder/share/submitNoisyStripJobs.py index fa034fd773f32751a71c04538775a1f5ab148e58..4bcb0acf24a53e2c1e88da7c523767ac34fcab4d 100755 --- a/Tracker/TrackerRecAlgs/NoisyStripFinder/share/submitNoisyStripJobs.py +++ b/Tracker/TrackerRecAlgs/NoisyStripFinder/share/submitNoisyStripJobs.py @@ -226,9 +226,10 @@ if __name__ == "__main__": f.write('if [[ $1 != "0" ]]; then\n') f.write(' exit $1\n') f.write('fi\n') + # Removing files used by the DAG will make this hang... # f.write('rm noise_{runstr}.dag.* \n') - f.write('rm *.log\n') - f.write('rm *.err\n') + # f.write('rm *.log\n') + # f.write('rm *.err\n') f.write('rm eventLoopHeartBeat.txt\n') f.write('rm *.cc\n') for job in submit_list: diff --git a/Tracker/TrackerRecAlgs/NoisyStripFinder/test/NoisyStripFinderDbg.py b/Tracker/TrackerRecAlgs/NoisyStripFinder/test/NoisyStripFinderDbg.py index f1d2ef1434110fa4a87a4567055e8f3d112f30c0..8b31e1b3db8f98e4cf8a535a7ca5f839fb142799 100755 --- a/Tracker/TrackerRecAlgs/NoisyStripFinder/test/NoisyStripFinderDbg.py +++ b/Tracker/TrackerRecAlgs/NoisyStripFinder/test/NoisyStripFinderDbg.py @@ -24,7 +24,7 @@ log.setLevel(DEBUG) Configurable.configurableRun3Behavior = True ConfigFlags.Input.Files = args.file -ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-02" +ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-03" ConfigFlags.IOVDb.DatabaseInstance = "OFLP200" ConfigFlags.Input.ProjectName = "data21" ConfigFlags.Input.isMC = False diff --git a/Tracker/TrackerRecAlgs/TrackerData/test/TI12TrackerSegmentFitDataDbg.py b/Tracker/TrackerRecAlgs/TrackerData/test/TI12TrackerSegmentFitDataDbg.py index b20d313f99654d07487651c645616b93a266789f..e69cdca114c30d2d72f0c27fbeed21746524e51b 100644 --- a/Tracker/TrackerRecAlgs/TrackerData/test/TI12TrackerSegmentFitDataDbg.py +++ b/Tracker/TrackerRecAlgs/TrackerData/test/TI12TrackerSegmentFitDataDbg.py @@ -22,7 +22,7 @@ Configurable.configurableRun3Behavior = True ConfigFlags.Input.Files = ['/home/tboeckh/tmp/Faser-Physics-006470-00093.raw_middleStation.SPs'] ConfigFlags.Output.ESDFileName = "TrackerSegmentFitData.ESD.pool.root" ConfigFlags.addFlag("Output.xAODFileName", f"TrackerSegmentFitData_xAOD.root") -ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-02" +ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-03" ConfigFlags.IOVDb.DatabaseInstance = "OFLP200" ConfigFlags.Input.ProjectName = "data21" ConfigFlags.Input.isMC = False diff --git a/Tracker/TrackerRecAlgs/TrackerSegmentFit/test/TrackerSegmentFitDbg.py b/Tracker/TrackerRecAlgs/TrackerSegmentFit/test/TrackerSegmentFitDbg.py index 75c46defbbb45d3c815f9d11e0091c83836a6e1e..7ca10a8b71dd3e80e0c705a09299c84537305876 100644 --- a/Tracker/TrackerRecAlgs/TrackerSegmentFit/test/TrackerSegmentFitDbg.py +++ b/Tracker/TrackerRecAlgs/TrackerSegmentFit/test/TrackerSegmentFitDbg.py @@ -29,7 +29,7 @@ ConfigFlags.Input.Files = [ '/eos/project-f/faser-commissioning/TI12Data/Run-005684/Faser-Physics-005684-00000.raw', ] ConfigFlags.Output.ESDFileName = "run005684-00000.ESD.pool.root" -ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-02" # Always needed; must match FaserVersion +ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-03" # Always needed; must match FaserVersion ConfigFlags.IOVDb.DatabaseInstance = "OFLP200" # Use MC conditions for now ConfigFlags.Input.ProjectName = "data21" # Needed to bypass autoconfig ConfigFlags.Input.isMC = False # Needed to bypass autoconfig @@ -98,4 +98,4 @@ replicaSvc.UseGeomSQLite = True sc = acc.run(maxEvents=-1) # Success should be 0 -sys.exit(not sc.isSuccess()) \ No newline at end of file +sys.exit(not sc.isSuccess()) diff --git a/Tracking/Acts/FaserActsGeometry/python/FaserActsMaterialMapping_jobOptions.py b/Tracking/Acts/FaserActsGeometry/python/FaserActsMaterialMapping_jobOptions.py index 92c1b6039a754f68dd5c562575a0dc3b9cc2e9d5..9a7e4995a8b28b4139826f8274b20ed1911bcf86 100644 --- a/Tracking/Acts/FaserActsGeometry/python/FaserActsMaterialMapping_jobOptions.py +++ b/Tracking/Acts/FaserActsGeometry/python/FaserActsMaterialMapping_jobOptions.py @@ -61,7 +61,7 @@ if "__main__" == __name__: ConfigFlags.Input.isMC = True ConfigFlags.Beam.Type = "collisions" ConfigFlags.GeoModel.FaserVersion = "FASERNU-03" - ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-02" # Always needed; must match FaserVersion + ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-03" # Always needed; must match FaserVersion ConfigFlags.TrackingGeometry.MaterialSource = "geometry-maps.json" ConfigFlags.GeoModel.Align.Dynamic = False diff --git a/Tracking/Acts/FaserActsGeometry/test/FaserActsWriteTrackingGeometry.py b/Tracking/Acts/FaserActsGeometry/test/FaserActsWriteTrackingGeometry.py index ed998b3b4607cf633e2825b5cb868c08039308d6..196a86099b66e0750a2b91f4803acbf0252bc321 100644 --- a/Tracking/Acts/FaserActsGeometry/test/FaserActsWriteTrackingGeometry.py +++ b/Tracking/Acts/FaserActsGeometry/test/FaserActsWriteTrackingGeometry.py @@ -19,7 +19,7 @@ Configurable.configurableRun3Behavior = True # Configure ConfigFlags.Input.Files = ["myevt4.HITS.pool.root"] #ConfigFlags.Output.RDOFileName = "myRDO_sp.pool.root" -ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-02" # Always needed; must match FaserVersion +ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-03" # Always needed; must match FaserVersion ConfigFlags.GeoModel.FaserVersion = "FASERNU-03" # Always needed #ConfigFlags.GeoModel.FaserVersion = "FASERNU-03" # Always needed # Workaround for bug/missing flag; unimportant otherwise diff --git a/Tracking/Acts/FaserActsKalmanFilter/CMakeLists.txt b/Tracking/Acts/FaserActsKalmanFilter/CMakeLists.txt index 9377c4716810301c16fe7ca606ba31e6f5ba318c..f93c094287a4966f84689abaa2615da2b2ef8882 100755 --- a/Tracking/Acts/FaserActsKalmanFilter/CMakeLists.txt +++ b/Tracking/Acts/FaserActsKalmanFilter/CMakeLists.txt @@ -39,8 +39,10 @@ atlas_add_component(FaserActsKalmanFilter MyTrackSeedTool.h FaserActsKalmanFilter/IdentifierLink.h FaserActsKalmanFilter/IndexSourceLink.h + FaserActsKalmanFilter/IFiducialParticleTool.h FaserActsKalmanFilter/ITrackFinderTool.h FaserActsKalmanFilter/ITrackSeedTool.h + FaserActsKalmanFilter/ITrackTruthMatchingTool.h KalmanFitterTool.h LinearFit.h # ClusterTrackSeedTool.h @@ -77,6 +79,8 @@ atlas_add_component(FaserActsKalmanFilter src/CombinatorialKalmanFilterAlg.cxx src/EffPlotTool.cxx src/FaserActsKalmanFilterAlg.cxx + src/FiducialParticleTool.h + src/FiducialParticleTool.cxx src/GhostBusters.cxx src/MyTrackSeedTool.cxx src/KalmanFitterTool.cxx @@ -101,6 +105,8 @@ atlas_add_component(FaserActsKalmanFilter src/TrackClassification.cxx src/TrackSeedWriterTool.cxx src/TrackSelection.cxx + src/TrackTruthMatchingTool.h + src/TrackTruthMatchingTool.cxx # src/TruthTrackFinderTool.cxx # src/TruthSeededTrackFinderTool.cxx src/ThreeStationTrackSeedTool.cxx diff --git a/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/IFiducialParticleTool.h b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/IFiducialParticleTool.h new file mode 100644 index 0000000000000000000000000000000000000000..1df9aeab2ce991ee5d683d92fa5efb72eca7a5dd --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/IFiducialParticleTool.h @@ -0,0 +1,28 @@ +/* + Copyright (C) 2002-2022 CERN for the benefit of the ATLAS and FASER + collaborations +*/ + +#ifndef FASERACTSKALMANFILTER_IFIDUCIALEVENTSELECTIONTOOL_H +#define FASERACTSKALMANFILTER_IFIDUCIALEVENTSELECTIONTOOL_H + +#include "CLHEP/Geometry/Point3D.h" + +class IFiducialParticleTool : virtual public IAlgTool { +public: + DeclareInterfaceID(IFiducialParticleTool, 1, 0); + + /** Check if truth hits for the given barcode exist and are in the + * fiducial volume (r < 100mm) in stations 1 to 3. + * @param barcode of a xAOD::TruthParticle + */ + virtual bool isFiducial(int barcode) const = 0; + + /** Return average truth position in each station. + * @param barcode of a xAOD::TruthParticle + */ + virtual std::array<HepGeom::Point3D<double>, 4> + getTruthPositions(int barcode) const = 0; +}; + +#endif // FASERACTSKALMANFILTER_IFIDUCIALEVENTSELECTIONTOOL_H diff --git a/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/ITrackTruthMatchingTool.h b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/ITrackTruthMatchingTool.h new file mode 100644 index 0000000000000000000000000000000000000000..045e597a9ebf916bad29665c6e07a4217c027ce8 --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/FaserActsKalmanFilter/ITrackTruthMatchingTool.h @@ -0,0 +1,21 @@ +/* + Copyright (C) 2002-2022 CERN for the benefit of the ATLAS and FASER + collaborations +*/ + +#ifndef FASERACTSKALMANFILTER_ITRACKTRUTHMATCHINGTOOL_H +#define FASERACTSKALMANFILTER_ITRACKTRUTHMATCHINGTOOL_H + +#include "GaudiKernel/IAlgTool.h" +#include "TrkTrack/Track.h" +#include "xAODTruth/TruthParticle.h" + +class ITrackTruthMatchingTool : virtual public IAlgTool { +public: + DeclareInterfaceID(ITrackTruthMatchingTool, 1, 0); + + virtual std::pair<const xAOD::TruthParticle*, int> + getTruthParticle(const Trk::Track *track) const = 0; +}; + +#endif /* FASERACTSKALMANFILTER_ITRACKTRUTHMATCHINGTOOL_H */ diff --git a/Tracking/Acts/FaserActsKalmanFilter/src/CircleFitTrackSeedTool.cxx b/Tracking/Acts/FaserActsKalmanFilter/src/CircleFitTrackSeedTool.cxx index 066698a478fbea03a6565a056afafd253e449a0d..41611bad5882de7e15ce3de15f6c4833fbf10581 100644 --- a/Tracking/Acts/FaserActsKalmanFilter/src/CircleFitTrackSeedTool.cxx +++ b/Tracking/Acts/FaserActsKalmanFilter/src/CircleFitTrackSeedTool.cxx @@ -7,6 +7,7 @@ #include "Identifier/Identifier.h" #include "Acts/Geometry/GeometryIdentifier.hpp" #include "CircleFit.h" +#include "Identifier/Identifier.h" #include "LinearFit.h" #include "TrackClassification.h" #include <array> @@ -264,12 +265,13 @@ CircleFitTrackSeedTool::Seed::Seed(const std::vector<Segment> &segments) : size = clusters.size(); } - void CircleFitTrackSeedTool::Seed::fit() { CircleFit::CircleData circleData(positions); CircleFit::Circle circle = CircleFit::circleFit(circleData); momentum = circle.r > 0 ? circle.r * 0.001 * 0.3 * 0.55 : 9999999.; - charge = circle.cy < 0 ? -1 : 1; + // the magnetic field bends a positively charged particle downwards, thus the + // y-component of the center of a fitted circle is negative. + charge = circle.cy < 0 ? 1 : -1; } void CircleFitTrackSeedTool::Seed::fakeFit(double B) { @@ -279,7 +281,9 @@ void CircleFitTrackSeedTool::Seed::fakeFit(double B) { cy = circle.cy; r = circle.r; momentum = r * 0.3 * B * m_MeV2GeV; - charge = circle.cy > 0 ? 1 : -1; + // the magnetic field bends a positively charged particle downwards, thus the + // y-component of the center of a fitted circle is negative. + charge = circle.cy < 0 ? 1 : -1; } void CircleFitTrackSeedTool::Seed::linearFit(const std::vector<Acts::Vector2> &points) { @@ -288,7 +292,6 @@ void CircleFitTrackSeedTool::Seed::linearFit(const std::vector<Acts::Vector2> &p c0 = origin[1] - origin[0] * c1; } - double CircleFitTrackSeedTool::Seed::getY(double z) { double sqt = std::sqrt(-cx*cx + 2*cx*z + r*r - z*z); return abs(cy - sqt) < abs(cy + sqt) ? cy - sqt : cy + sqt; diff --git a/Tracking/Acts/FaserActsKalmanFilter/src/FiducialParticleTool.cxx b/Tracking/Acts/FaserActsKalmanFilter/src/FiducialParticleTool.cxx new file mode 100644 index 0000000000000000000000000000000000000000..101ddfdf99a645aaef69f6d824e782ff7525928f --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/src/FiducialParticleTool.cxx @@ -0,0 +1,91 @@ +#include "FiducialParticleTool.h" +#include "GeoPrimitives/CLHEPtoEigenConverter.h" +#include "TrackerIdentifier/FaserSCT_ID.h" +#include "TrackerReadoutGeometry/SCT_DetectorManager.h" +#include "TrackerReadoutGeometry/SiDetectorElement.h" + +constexpr float NaN = std::numeric_limits<double>::quiet_NaN(); + +FiducialParticleTool::FiducialParticleTool(const std::string &type, + const std::string &name, + const IInterface *parent) + : base_class(type, name, parent) {} + +StatusCode FiducialParticleTool::initialize() { + ATH_CHECK(m_siHitCollectionKey.initialize()); + ATH_CHECK(detStore()->retrieve(m_sctHelper, "FaserSCT_ID")); + ATH_CHECK(detStore()->retrieve(m_detMgr, "SCT")); + return StatusCode::SUCCESS; +} + +StatusCode FiducialParticleTool::finalize() { return StatusCode::SUCCESS; } + +bool FiducialParticleTool::isFiducial(int barcode) const { + auto positions = getTruthPositions(barcode); + bool isFiducial{true}; + for (int station = 1; station < 4; ++station) { + double x{positions[station].x()}; + double y{positions[station].y()}; + if (std::isnan(x) || std::isnan(y) || (x * x + y * y > 100 * 100)) + isFiducial = false; + } + return isFiducial; +} + +HepGeom::Point3D<double> +FiducialParticleTool::getGlobalPosition(const FaserSiHit &hit) const { + Identifier waferId = + m_sctHelper->wafer_id(hit.getStation(), hit.getPlane(), hit.getRow(), + hit.getModule(), hit.getSensor()); + auto localStartPos = hit.localStartPosition(); + auto localEndPos = hit.localEndPosition(); + HepGeom::Point3D<double> localPos = 0.5 * (localEndPos + localStartPos); + const TrackerDD::SiDetectorElement *element = + m_detMgr->getDetectorElement(waferId); + auto globalPosition = + Amg::EigenTransformToCLHEP(element->transformHit()) * localPos; + return globalPosition; +} + +std::array<HepGeom::Point3D<double>, 4> +FiducialParticleTool::getTruthPositions(int barcode) const { + // initialize positions as NaN + std::array<HepGeom::Point3D<double>, 4> positions{}; + for (auto &station : positions) { + station.setX(NaN); + station.setY(NaN); + station.setZ(NaN); + } + + // get simulated hits + SG::ReadHandle<FaserSiHitCollection> siHitCollection(m_siHitCollectionKey); + if (!siHitCollection.isValid()) { + ATH_MSG_WARNING("FaserSiHitCollection not valid."); + return positions; + } + + // create map with truth positions in each station + std::array<std::vector<HepGeom::Point3D<double>>, 4> hitMap{}; + for (const FaserSiHit &hit : *siHitCollection) { + if (hit.trackNumber() == barcode) { + auto position = getGlobalPosition(hit); + hitMap[hit.getStation()].push_back(position); + } + } + + // calculate average position in each station + for (int station = 0; station < 4; ++station) { + std::vector<HepGeom::Point3D<double>> &hits{hitMap[station]}; + if (hits.empty()) { + continue; + } else { + // calculate average position of all FaserSiHits in a station + auto const count = static_cast<double>(hits.size()); + HepGeom::Point3D<double> sums{}; + for (const HepGeom::Point3D<double> &hit : hits) + sums += hit; + positions[station] = sums / count; + } + } + return positions; +} diff --git a/Tracking/Acts/FaserActsKalmanFilter/src/FiducialParticleTool.h b/Tracking/Acts/FaserActsKalmanFilter/src/FiducialParticleTool.h new file mode 100644 index 0000000000000000000000000000000000000000..8d1435734c6982e9dcbd0abd52acb07003914366 --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/src/FiducialParticleTool.h @@ -0,0 +1,37 @@ +#ifndef FASERACTSKALMANFILTER_FIDUCIALEVENTSELECTIONTOOL_H +#define FASERACTSKALMANFILTER_FIDUCIALEVENTSELECTIONTOOL_H + +#include "AthenaBaseComps/AthAlgTool.h" +#include "FaserActsKalmanFilter/IFiducialParticleTool.h" +#include "GeoPrimitives/GeoPrimitives.h" +#include "TrackerSimEvent/FaserSiHitCollection.h" + +class FaserSCT_ID; +namespace TrackerDD { +class SCT_DetectorManager; +} + +class FiducialParticleTool : public extends<AthAlgTool, IFiducialParticleTool> { +public: + FiducialParticleTool(const std::string &type, const std::string &name, + const IInterface *parent); + virtual ~FiducialParticleTool() = default; + virtual StatusCode initialize() override; + virtual StatusCode finalize() override; + + bool isFiducial(int barcode) const override; + + std::array<HepGeom::Point3D<double>, 4> + getTruthPositions(int barcode) const override; + +private: + HepGeom::Point3D<double> getGlobalPosition(const FaserSiHit &hit) const; + + SG::ReadHandleKey<FaserSiHitCollection> m_siHitCollectionKey{ + this, "FaserSiHitCollection", "SCT_Hits"}; + + const FaserSCT_ID *m_sctHelper{nullptr}; + const TrackerDD::SCT_DetectorManager *m_detMgr{nullptr}; +}; + +#endif // FASERACTSKALMANFILTER_FIDUCIALEVENTSELECTIONTOOL_H diff --git a/Tracking/Acts/FaserActsKalmanFilter/src/TrackTruthMatchingTool.cxx b/Tracking/Acts/FaserActsKalmanFilter/src/TrackTruthMatchingTool.cxx new file mode 100644 index 0000000000000000000000000000000000000000..502faa3d4bb4dde421f63d2105f8d5525c67a0be --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/src/TrackTruthMatchingTool.cxx @@ -0,0 +1,103 @@ +#include "TrackTruthMatchingTool.h" +#include "TrackerPrepRawData/FaserSCT_Cluster.h" +#include "TrackerRIO_OnTrack/FaserSCT_ClusterOnTrack.h" + +TrackTruthMatchingTool::TrackTruthMatchingTool(const std::string &type, + const std::string &name, + const IInterface *parent) + : base_class(type, name, parent) {} + +StatusCode TrackTruthMatchingTool::initialize() { + ATH_CHECK(m_simDataCollectionKey.initialize()); + ATH_CHECK(m_truthParticleContainerKey.initialize()); + return StatusCode::SUCCESS; +} + +std::pair<const xAOD::TruthParticle *, int> +TrackTruthMatchingTool::getTruthParticle(const Trk::Track *track) const { + const xAOD::TruthParticle *truthParticle = nullptr; + const EventContext &ctx = Gaudi::Hive::currentContext(); + SG::ReadHandle<xAOD::TruthParticleContainer> truthParticleContainer{ + m_truthParticleContainerKey, ctx}; + if (!truthParticleContainer.isValid()) { + ATH_MSG_WARNING("xAOD::TruthParticleContainer is not valid."); + return {truthParticle, -1}; + } + SG::ReadHandle<TrackerSimDataCollection> simDataCollection{ + m_simDataCollectionKey, ctx}; + if (!simDataCollection.isValid()) { + ATH_MSG_WARNING("TrackerSimDataCollection is not valid."); + return {truthParticle, -1}; + } + std::vector<ParticleHitCount> particleHitCounts{}; + identifyContributingParticles(*track, *simDataCollection, particleHitCounts); + if (particleHitCounts.empty()) { + ATH_MSG_WARNING("Cannot find any truth particle matched to the track."); + return {truthParticle, -1}; + } + int barcode = particleHitCounts.front().barcode; + int hitCount = particleHitCounts.front().hitCount; + auto it = std::find_if(truthParticleContainer->begin(), + truthParticleContainer->end(), + [barcode](const xAOD::TruthParticle_v1 *particle) { + return particle->barcode() == barcode; + }); + if (it == truthParticleContainer->end()) { + ATH_MSG_WARNING("Cannot find particle with barcode " + << barcode << " in truth particle container."); + return {truthParticle, -1}; + } + truthParticle = *it; + return {truthParticle, hitCount}; +} + +StatusCode TrackTruthMatchingTool::finalize() { return StatusCode::SUCCESS; } + +void TrackTruthMatchingTool::increaseHitCount( + std::vector<ParticleHitCount> &particleHitCounts, int barcode) { + auto it = std::find_if( + particleHitCounts.begin(), particleHitCounts.end(), + [=](const ParticleHitCount &phc) { return (phc.barcode == barcode); }); + // either increase count if we saw the particle before or add it + if (it != particleHitCounts.end()) { + it->hitCount += 1u; + } else { + particleHitCounts.push_back({barcode, 1u}); + } +} + +void TrackTruthMatchingTool::sortHitCount( + std::vector<ParticleHitCount> &particleHitCounts) { + std::sort(particleHitCounts.begin(), particleHitCounts.end(), + [](const ParticleHitCount &lhs, const ParticleHitCount &rhs) { + return (lhs.hitCount > rhs.hitCount); + }); +} + +void TrackTruthMatchingTool::identifyContributingParticles( + const Trk::Track &track, const TrackerSimDataCollection &simDataCollection, + std::vector<ParticleHitCount> &particleHitCounts) { + for (const Trk::MeasurementBase *meas : *track.measurementsOnTrack()) { + const auto *clusterOnTrack = + dynamic_cast<const Tracker::FaserSCT_ClusterOnTrack *>(meas); + if (!clusterOnTrack) + continue; + std::vector<int> barcodes{}; + const Tracker::FaserSCT_Cluster *cluster = clusterOnTrack->prepRawData(); + for (Identifier id : cluster->rdoList()) { + if (simDataCollection.count(id) == 0) + continue; + const auto &deposits = simDataCollection.at(id).getdeposits(); + for (const TrackerSimData::Deposit &deposit : deposits) { + int barcode = deposit.first->barcode(); + // count each barcode only once for a wafer + if (std::find(barcodes.begin(), barcodes.end(), barcode) == + barcodes.end()) { + barcodes.push_back(barcode); + increaseHitCount(particleHitCounts, barcode); + } + } + } + } + sortHitCount(particleHitCounts); +} diff --git a/Tracking/Acts/FaserActsKalmanFilter/src/TrackTruthMatchingTool.h b/Tracking/Acts/FaserActsKalmanFilter/src/TrackTruthMatchingTool.h new file mode 100644 index 0000000000000000000000000000000000000000..94ab440588b4353a4d45a8d7a15a61aac434f6a3 --- /dev/null +++ b/Tracking/Acts/FaserActsKalmanFilter/src/TrackTruthMatchingTool.h @@ -0,0 +1,40 @@ +#ifndef FASERACTSKALMANFILTER_TRACKTRUTHMATCHINGTOOL_H +#define FASERACTSKALMANFILTER_TRACKTRUTHMATCHINGTOOL_H + +#include "AthenaBaseComps/AthAlgTool.h" +#include "FaserActsKalmanFilter/ITrackTruthMatchingTool.h" +#include "TrackerSimData/TrackerSimDataCollection.h" +#include "TrkTrack/Track.h" +#include "xAODTruth/TruthParticleContainer.h" + +class TrackTruthMatchingTool + : public extends<AthAlgTool, ITrackTruthMatchingTool> { +public: + TrackTruthMatchingTool(const std::string &type, const std::string &name, + const IInterface *parent); + virtual ~TrackTruthMatchingTool() = default; + virtual StatusCode initialize() override; + virtual StatusCode finalize() override; + + std::pair<const xAOD::TruthParticle*, int> + getTruthParticle(const Trk::Track *track) const; + +private: + struct ParticleHitCount { + int barcode; + size_t hitCount; + }; + static void increaseHitCount(std::vector<ParticleHitCount> &particleHitCounts, + int particleId); + static void sortHitCount(std::vector<ParticleHitCount> &particleHitCounts); + static void identifyContributingParticles( + const Trk::Track &track, const TrackerSimDataCollection &simDataCollection, + std::vector<ParticleHitCount> &particleHitCounts); + + SG::ReadHandleKey<TrackerSimDataCollection> m_simDataCollectionKey{ + this, "TrackerSimDataCollection", "SCT_SDO_Map"}; + SG::ReadHandleKey<xAOD::TruthParticleContainer> m_truthParticleContainerKey{ + this, "ParticleContainer", "TruthParticles"}; +}; + +#endif /* FASERACTSKALMANFILTER_TRACKTRUTHMATCHINGTOOL_H */ diff --git a/Tracking/Acts/FaserActsKalmanFilter/src/components/FaserActsKalmanFilter_entries.cxx b/Tracking/Acts/FaserActsKalmanFilter/src/components/FaserActsKalmanFilter_entries.cxx index 967f80641f7846d303be4632c252ca30eaab6436..d9fefbddfb3b5e651f5ac697ac231bb9e41918d3 100755 --- a/Tracking/Acts/FaserActsKalmanFilter/src/components/FaserActsKalmanFilter_entries.cxx +++ b/Tracking/Acts/FaserActsKalmanFilter/src/components/FaserActsKalmanFilter_entries.cxx @@ -29,6 +29,8 @@ #include "../CircleFitTrackSeedTool.h" #include "../GhostBusters.h" #include "../CreateTrkTrackTool.h" +#include "../TrackTruthMatchingTool.h" +#include "../FiducialParticleTool.h" DECLARE_COMPONENT(FaserActsKalmanFilterAlg) DECLARE_COMPONENT(CombinatorialKalmanFilterAlg) @@ -57,3 +59,5 @@ DECLARE_COMPONENT(SeedingAlg) DECLARE_COMPONENT(CircleFitTrackSeedTool) DECLARE_COMPONENT(GhostBusters) DECLARE_COMPONENT(CreateTrkTrackTool) +DECLARE_COMPONENT(TrackTruthMatchingTool) +DECLARE_COMPONENT(FiducialParticleTool) diff --git a/Tracking/Acts/FaserActsKalmanFilter/test/CKF2.py b/Tracking/Acts/FaserActsKalmanFilter/test/CKF2.py index 27c50d9a8b397776ccf19e810ff981afa47a6b67..3d8e9e3fb2f03e126b4d7c39f3680126592eaa61 100644 --- a/Tracking/Acts/FaserActsKalmanFilter/test/CKF2.py +++ b/Tracking/Acts/FaserActsKalmanFilter/test/CKF2.py @@ -27,7 +27,7 @@ Configurable.configurableRun3Behavior = True ConfigFlags.Input.Files = args.file ConfigFlags.addFlag("Output.xAODFileName", f"CKF.xAOD.root") ConfigFlags.Output.ESDFileName = "CKF.ESD.pool.root" -ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-02" +ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-03" ConfigFlags.GeoModel.FaserVersion = "FASERNU-03" ConfigFlags.GeoModel.Align.Dynamic = False ConfigFlags.Beam.NumberOfCollisions = 0. diff --git a/Tracking/Acts/FaserActsKalmanFilter/test/TI12CKF2.py b/Tracking/Acts/FaserActsKalmanFilter/test/TI12CKF2.py index cf63c3e400de073ad330df6498129996863b6c3a..37ac15b268712bc98cea7ccd4134fe0545176cde 100644 --- a/Tracking/Acts/FaserActsKalmanFilter/test/TI12CKF2.py +++ b/Tracking/Acts/FaserActsKalmanFilter/test/TI12CKF2.py @@ -30,7 +30,7 @@ Configurable.configurableRun3Behavior = True ConfigFlags.Input.Files = args.file ConfigFlags.Output.ESDFileName = "CKF.ESD.pool.root" ConfigFlags.addFlag("Output.xAODFileName", f"CKF.xAOD.root") -ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-02" +ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-03" ConfigFlags.IOVDb.DatabaseInstance = "OFLP200" ConfigFlags.Input.ProjectName = "data22" ConfigFlags.Input.isMC = False diff --git a/Tracking/Acts/FaserActsKalmanFilter/test/TI12KalmanFilter.py b/Tracking/Acts/FaserActsKalmanFilter/test/TI12KalmanFilter.py index 11b7e4217bed8400426f4257ef5cf43f5b7adbfd..ed4be62cd88dcb5fa2280509da8af121b9eaaf85 100644 --- a/Tracking/Acts/FaserActsKalmanFilter/test/TI12KalmanFilter.py +++ b/Tracking/Acts/FaserActsKalmanFilter/test/TI12KalmanFilter.py @@ -24,7 +24,7 @@ Configurable.configurableRun3Behavior = True ConfigFlags.Input.Files = ['/home/tboeckh/tmp/Faser-Physics-006470-00093.raw_middleStation.SPs'] ConfigFlags.Output.ESDFileName = "MiddleStation-KalmanFilter.ESD.pool.root" ConfigFlags.Output.AODFileName = "MiddleStation-KalmanFilter.AOD.pool.root" -ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-02" +ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-03" ConfigFlags.IOVDb.DatabaseInstance = "OFLP200" ConfigFlags.Input.ProjectName = "data21" ConfigFlags.Input.isMC = False diff --git a/Waveform/WaveDigiTools/share/WaveformDigiAndRecoExample_jobOptions.py b/Waveform/WaveDigiTools/share/WaveformDigiAndRecoExample_jobOptions.py index 779031828c9c5736f9403e403514e19285029499..cbe155043db36bc9dc91ef6383ebd2db1d89edf7 100644 --- a/Waveform/WaveDigiTools/share/WaveformDigiAndRecoExample_jobOptions.py +++ b/Waveform/WaveDigiTools/share/WaveformDigiAndRecoExample_jobOptions.py @@ -21,7 +21,7 @@ if __name__ == "__main__": log.setLevel(VERBOSE) - ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-02" # Always needed; must match FaserVersion + ConfigFlags.IOVDb.GlobalTag = "OFLCOND-FASER-03" # Always needed; must match FaserVersion ConfigFlags.IOVDb.DatabaseInstance = "OFLP200" # Use MC conditions for now ConfigFlags.Input.ProjectName = "mc21" # Needed to bypass autoconfig ConfigFlags.Input.isMC = True # Needed to bypass autoconfig diff --git a/Waveform/WaveformConditions/WaveformConditionsTools/python/WaveformRangeConfig.py b/Waveform/WaveformConditions/WaveformConditionsTools/python/WaveformRangeConfig.py index 6450bcec88b3cb8c7194b01edeb59aa6b97e242f..8ac69d912af498475d443f58b3583fc6fdb614c8 100644 --- a/Waveform/WaveformConditions/WaveformConditionsTools/python/WaveformRangeConfig.py +++ b/Waveform/WaveformConditions/WaveformConditionsTools/python/WaveformRangeConfig.py @@ -20,8 +20,14 @@ def WaveformRangeCfg(flags, **kwargs): acc = ComponentAccumulator() # tool = kwargs.get("WaveformRangeTool", WaveformRangeTool(flags)) # Probably need to figure this out! - dbInstance = kwargs.get("dbInstance", "TDAQ_OFL") + + dbInstance = kwargs.get("dbInstance", "COOLOFL_DIGITIZER") dbFolder = kwargs.get("dbFolder", "/WAVE/DAQ/Range") - acc.merge(addFolders(flags, dbFolder, dbInstance, className="CondAttrListCollection")) + dbName = flags.IOVDb.DatabaseInstance # e.g. CONDBR3 + + # COOLOFL_DIGITIZER is not known to ATLAS IOVDBSvc + # Must use non-shorthand folder specification here + folder_string = f"<db>{dbInstance}/{dbName}</db> {dbFolder}" + acc.merge(addFolders(flags, folder_string, className="CondAttrListCollection")) return acc diff --git a/xAOD/xAODFaserCalorimeter/Root/CalorimeterHitAuxContainer_v1.cxx b/xAOD/xAODFaserCalorimeter/Root/CalorimeterHitAuxContainer_v1.cxx index 6f6edf3e4c520dbf32bb816addb74f4ad3eae23f..277ecd25c0d1e2056a6c2a1eeef101f5570f80c2 100644 --- a/xAOD/xAODFaserCalorimeter/Root/CalorimeterHitAuxContainer_v1.cxx +++ b/xAOD/xAODFaserCalorimeter/Root/CalorimeterHitAuxContainer_v1.cxx @@ -10,11 +10,13 @@ namespace xAOD { CalorimeterHitAuxContainer_v1::CalorimeterHitAuxContainer_v1() : AuxContainerBase() { - AUX_VARIABLE(localtime); - AUX_VARIABLE(bcid_time); - AUX_VARIABLE(raw_energy); + AUX_VARIABLE(channel); + AUX_VARIABLE(Nmip); + AUX_VARIABLE(E_dep); + AUX_VARIABLE(E_EM); + AUX_VARIABLE(fit_to_raw_ratio); - AUX_VARIABLE(caloLinks); + AUX_VARIABLE(WaveformLink); } } // namespace xAOD diff --git a/xAOD/xAODFaserCalorimeter/Root/CalorimeterHit_v1.cxx b/xAOD/xAODFaserCalorimeter/Root/CalorimeterHit_v1.cxx index 5e7a69ecc024dc3ecb70df95f1e623c4bc4e09fc..ff592dff67ca5c37bf0ea954dcc9eb63f3a26a28 100644 --- a/xAOD/xAODFaserCalorimeter/Root/CalorimeterHit_v1.cxx +++ b/xAOD/xAODFaserCalorimeter/Root/CalorimeterHit_v1.cxx @@ -13,41 +13,45 @@ namespace xAOD { CalorimeterHit_v1::CalorimeterHit_v1() : SG::AuxElement() { } - AUXSTORE_PRIMITIVE_SETTER_AND_GETTER( CalorimeterHit_v1, float, localtime, set_localtime ) + AUXSTORE_PRIMITIVE_SETTER_AND_GETTER( CalorimeterHit_v1, unsigned int, channel, set_channel ) - AUXSTORE_PRIMITIVE_SETTER_AND_GETTER( CalorimeterHit_v1, float, bcidtime, set_bcidtime ) + AUXSTORE_PRIMITIVE_SETTER_AND_GETTER( CalorimeterHit_v1, float, Nmip, set_Nmip ) - AUXSTORE_PRIMITIVE_SETTER_AND_GETTER( CalorimeterHit_v1, float, raw_energy, set_raw_energy ) + AUXSTORE_PRIMITIVE_SETTER_AND_GETTER( CalorimeterHit_v1, float, E_dep, set_E_dep ) + + AUXSTORE_PRIMITIVE_SETTER_AND_GETTER( CalorimeterHit_v1, float, E_EM, set_E_EM ) + + AUXSTORE_PRIMITIVE_SETTER_AND_GETTER( CalorimeterHit_v1, float, fit_to_raw_ratio, set_fit_to_raw_ratio ) // setters and getters for the Calo WaveformHit links AUXSTORE_OBJECT_SETTER_AND_GETTER( CalorimeterHit_v1, CalorimeterHit_v1::WaveformHitLinks_t, - caloWaveformLinks, - setCaloWaveformLinks ) + WaveformLinks, + setWaveformLinks ) - static const SG::AuxElement::Accessor< CalorimeterHit_v1::WaveformHitLinks_t > caloHitAcc( "caloWaveformLinks" ); + static const SG::AuxElement::Accessor< CalorimeterHit_v1::WaveformHitLinks_t > HitAcc( "WaveformLinks" ); - const WaveformHit* CalorimeterHit_v1::caloHit( size_t i ) const { - return ( *caloHitAcc( *this )[ i ] ); + const WaveformHit* CalorimeterHit_v1::Hit( size_t i ) const { + return ( *HitAcc( *this )[ i ] ); } - size_t CalorimeterHit_v1::nCaloHits() const { - return caloHitAcc( *this ).size(); + size_t CalorimeterHit_v1::nHits() const { + return HitAcc( *this ).size(); } - void CalorimeterHit_v1::addCaloHit( const xAOD::WaveformHitContainer* pWaveformHitContainer, + void CalorimeterHit_v1::addHit( const xAOD::WaveformHitContainer* pWaveformHitContainer, const xAOD::WaveformHit* pWaveformHit) { ElementLink< xAOD::WaveformHitContainer > linkToWaveformHit; linkToWaveformHit.toContainedElement(*pWaveformHitContainer, pWaveformHit); - caloHitAcc( *this ).push_back( linkToWaveformHit ); + HitAcc( *this ).push_back( linkToWaveformHit ); return; } - void CalorimeterHit_v1::clearCaloWaveformLinks() { - caloHitAcc( *this ).clear(); + void CalorimeterHit_v1::clearWaveformLinks() { + HitAcc( *this ).clear(); return; } @@ -57,8 +61,8 @@ namespace xAOD { std::ostream& operator<<(std::ostream& s, const xAOD::CalorimeterHit_v1& hit) { s << "xAODCalorimeterHit:" - << " local time=" << hit.localtime() - << " raw_energy=" << hit.raw_energy() + << " channel = " << hit.channel() + << ", E_dep = " << hit.E_dep() << std::endl; return s; diff --git a/xAOD/xAODFaserCalorimeter/xAODFaserCalorimeter/versions/CalorimeterHitAuxContainer_v1.h b/xAOD/xAODFaserCalorimeter/xAODFaserCalorimeter/versions/CalorimeterHitAuxContainer_v1.h index 7e61261eb4bd10f106d03b2a85f9918b82ce7944..230da2716246909fcf85653c288dc043aa9929a5 100644 --- a/xAOD/xAODFaserCalorimeter/xAODFaserCalorimeter/versions/CalorimeterHitAuxContainer_v1.h +++ b/xAOD/xAODFaserCalorimeter/xAODFaserCalorimeter/versions/CalorimeterHitAuxContainer_v1.h @@ -29,13 +29,16 @@ namespace xAOD { private: /// @name Basic variables ///@ { - std::vector<float> localtime; - std::vector<float> bcid_time; - std::vector<float> raw_energy; + std::vector<unsigned int> channel; + std::vector<float> Nmip; + std::vector<float> E_dep; + std::vector<float> E_EM; + std::vector<float> fit_to_raw_ratio; typedef std::vector< ElementLink< WaveformHitContainer > > WaveformHitLink_t; - std::vector< WaveformHitLink_t > caloLinks; - std::vector< WaveformHitLink_t > preshowerLinks; + std::vector< WaveformHitLink_t > WaveformLink; + //std::vector< WaveformHitLink_t > caloLinks; + //std::vector< WaveformHitLink_t > preshowerLinks; ///@} diff --git a/xAOD/xAODFaserCalorimeter/xAODFaserCalorimeter/versions/CalorimeterHit_v1.h b/xAOD/xAODFaserCalorimeter/xAODFaserCalorimeter/versions/CalorimeterHit_v1.h index d9bb35047e6a75d6dac12dc0ba0eb47e3bceb684..c27d9f033efc6eebaeb2120440a8855362b77700 100644 --- a/xAOD/xAODFaserCalorimeter/xAODFaserCalorimeter/versions/CalorimeterHit_v1.h +++ b/xAOD/xAODFaserCalorimeter/xAODFaserCalorimeter/versions/CalorimeterHit_v1.h @@ -35,29 +35,35 @@ namespace xAOD { /// @{ /// Best results - float localtime() const; - void set_localtime(float value); + unsigned int channel() const; + void set_channel(unsigned int value); - float bcidtime() const; - void set_bcidtime(float value); + float Nmip() const; + void set_Nmip(float value); - float raw_energy() const; - void set_raw_energy(float value); + float E_dep() const; + void set_E_dep(float value); + + float E_EM() const; + void set_E_EM(float value); + + float fit_to_raw_ratio() const; + void set_fit_to_raw_ratio(float value); // Waveform Hits typedef std::vector< ElementLink< xAOD::WaveformHitContainer > > WaveformHitLinks_t; // Contributing Calorimeter Waveform Hits - const WaveformHitLinks_t& caloWaveformLinks() const; - void setCaloWaveformLinks( const WaveformHitLinks_t& caloWaveforms ); + const WaveformHitLinks_t& WaveformLinks() const; + void setWaveformLinks( const WaveformHitLinks_t& Waveforms ); // Remove all waveform hits - void clearCaloWaveformLinks(); + void clearWaveformLinks(); // Get the pointer to a given waveform hit - const WaveformHit* caloHit( size_t i ) const; + const WaveformHit* Hit( size_t i ) const; // Get the number of waveform hits - size_t nCaloHits() const; + size_t nHits() const; // Add a waveform hit - void addCaloHit( const xAOD::WaveformHitContainer*, const xAOD::WaveformHit*); + void addHit( const xAOD::WaveformHitContainer*, const xAOD::WaveformHit*); // // Contributing Preshower Waveform Hits // const WaveformHitLinks_t& preshowerWaveformLinks() const; diff --git a/xAOD/xAODFaserLHC/CMakeLists.txt b/xAOD/xAODFaserLHC/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..577da2cc72aa0ecb03a16a9b0b440b2eaf2da3eb --- /dev/null +++ b/xAOD/xAODFaserLHC/CMakeLists.txt @@ -0,0 +1,27 @@ +# Copyright (C) 2020 CERN for the benefit of the FASER collaboration + +# Declare the package name. +atlas_subdir( xAODFaserLHC ) + +# External dependencies. +find_package( xAODUtilities ) + +# Component(s) in the package. +atlas_add_library( xAODFaserLHC + xAODFaserLHC/*.h xAODFaserLHC/versions/*.h Root/*.cxx + PUBLIC_HEADERS xAODFaserLHC + LINK_LIBRARIES xAODCore ) + +atlas_add_xaod_smart_pointer_dicts( + INPUT xAODFaserLHC/selection.xml + OUTPUT _selectionFile + OBJECTS "xAOD::FaserLHCData_v1" "xAOD::FaserLHCDataAux_v1") + +atlas_add_dictionary( xAODFaserLHCDict + xAODFaserLHC/xAODFaserLHCDict.h + ${_selectionFile} + LINK_LIBRARIES xAODCore xAODFaserLHC + EXTRA_FILES Root/dict/*.cxx ) + +# Understand what this does... +atlas_generate_cliddb( xAODFaserLHC ) diff --git a/xAOD/xAODFaserLHC/Root/FaserLHCDataAux_v1.cxx b/xAOD/xAODFaserLHC/Root/FaserLHCDataAux_v1.cxx new file mode 100644 index 0000000000000000000000000000000000000000..e9b981b33b5252b2cd5d627096462468c517e7e3 --- /dev/null +++ b/xAOD/xAODFaserLHC/Root/FaserLHCDataAux_v1.cxx @@ -0,0 +1,54 @@ +/* + Copyright (C) 2020 CERN for the benefit of the FASER collaboration +*/ + +// $Id: $ + +// Local include(s): +#include "xAODFaserLHC/versions/FaserLHCDataAux_v1.h" + +namespace xAOD { + + FaserLHCDataAux_v1::FaserLHCDataAux_v1() + : AuxInfoBase(), + fillNumber(0), + machineMode(""), + beamMode(""), + beamType1(0), + beamType2(0), + betaStar(0), + crossingAngle(0), + stableBeams(false), + injectionScheme(""), + numBunchBeam1(0), + numBunchBeam2(0), + numBunchColliding(0), + distanceToCollidingBCID(0), + distanceToUnpairedB1(0), + distanceToUnpairedB2(0), + distanceToInboundB1(0), + distanceToTrainStart(0), + distanceToPreviousColliding(0) + { + AUX_VARIABLE( fillNumber ); + AUX_VARIABLE( machineMode ); + AUX_VARIABLE( beamMode ); + AUX_VARIABLE( beamType1 ); + AUX_VARIABLE( beamType2 ); + AUX_VARIABLE( betaStar ); + AUX_VARIABLE( crossingAngle ); + AUX_VARIABLE( stableBeams ); + AUX_VARIABLE( injectionScheme ); + AUX_VARIABLE( numBunchBeam1 ); + AUX_VARIABLE( numBunchBeam2 ); + AUX_VARIABLE( numBunchColliding ); + AUX_VARIABLE( distanceToCollidingBCID ); + AUX_VARIABLE( distanceToUnpairedB1 ); + AUX_VARIABLE( distanceToUnpairedB2 ); + AUX_VARIABLE( distanceToInboundB1 ); + AUX_VARIABLE( distanceToTrainStart ); + AUX_VARIABLE( distanceToPreviousColliding ); + + } + +} // namespace xAOD diff --git a/xAOD/xAODFaserLHC/Root/FaserLHCData_v1.cxx b/xAOD/xAODFaserLHC/Root/FaserLHCData_v1.cxx new file mode 100644 index 0000000000000000000000000000000000000000..b09c8c85dcc0b19ae7fea0120c79a706336d0387 --- /dev/null +++ b/xAOD/xAODFaserLHC/Root/FaserLHCData_v1.cxx @@ -0,0 +1,92 @@ +/* + Copyright (C) 2020 CERN for the benefit of the FASER collaboration +*/ + +// $Id: $ + +// xAOD include(s): +#include "xAODCore/AuxStoreAccessorMacros.h" + +// Local include(s): +#include "xAODFaserLHC/versions/FaserLHCData_v1.h" + +namespace xAOD { + + FaserLHCData_v1::FaserLHCData_v1() + : SG::AuxElement() { + } + + ///////////////////////////////////////////////////////////////////////////// + // + // Implementation for the start time functions + AUXSTORE_PRIMITIVE_SETTER_AND_GETTER( FaserLHCData_v1, unsigned int, + fillNumber, set_fillNumber ) + + AUXSTORE_PRIMITIVE_SETTER_AND_GETTER( FaserLHCData_v1, std::string, + machineMode, set_machineMode ) + + AUXSTORE_PRIMITIVE_SETTER_AND_GETTER( FaserLHCData_v1, std::string, + beamMode, set_beamMode ) + + AUXSTORE_PRIMITIVE_SETTER_AND_GETTER( FaserLHCData_v1, int, + beamType1, set_beamType1 ) + + AUXSTORE_PRIMITIVE_SETTER_AND_GETTER( FaserLHCData_v1, int, + beamType2, set_beamType2 ) + + AUXSTORE_PRIMITIVE_SETTER_AND_GETTER( FaserLHCData_v1, float, + betaStar, set_betaStar ) + + AUXSTORE_PRIMITIVE_SETTER_AND_GETTER( FaserLHCData_v1, float, + crossingAngle, set_crossingAngle ) + + AUXSTORE_PRIMITIVE_SETTER_AND_GETTER( FaserLHCData_v1, bool, + stableBeams, set_stableBeams ) + + AUXSTORE_PRIMITIVE_SETTER_AND_GETTER( FaserLHCData_v1, std::string, + injectionScheme, set_injectionScheme ) + + AUXSTORE_PRIMITIVE_SETTER_AND_GETTER( FaserLHCData_v1, unsigned int, + numBunchBeam1, set_numBunchBeam1 ) + + AUXSTORE_PRIMITIVE_SETTER_AND_GETTER( FaserLHCData_v1, unsigned int, + numBunchBeam2, set_numBunchBeam2 ) + + AUXSTORE_PRIMITIVE_SETTER_AND_GETTER( FaserLHCData_v1, unsigned int, + numBunchColliding, set_numBunchColliding ) + + AUXSTORE_PRIMITIVE_SETTER_AND_GETTER( FaserLHCData_v1, int, + distanceToCollidingBCID, set_distanceToCollidingBCID ) + + AUXSTORE_PRIMITIVE_SETTER_AND_GETTER( FaserLHCData_v1, int, + distanceToUnpairedB1, set_distanceToUnpairedB1 ) + + AUXSTORE_PRIMITIVE_SETTER_AND_GETTER( FaserLHCData_v1, int, + distanceToUnpairedB2, set_distanceToUnpairedB2 ) + + AUXSTORE_PRIMITIVE_SETTER_AND_GETTER( FaserLHCData_v1, int, + distanceToInboundB1, set_distanceToInboundB1 ) + + AUXSTORE_PRIMITIVE_SETTER_AND_GETTER( FaserLHCData_v1, unsigned int, + distanceToTrainStart, set_distanceToTrainStart ) + + AUXSTORE_PRIMITIVE_SETTER_AND_GETTER( FaserLHCData_v1, unsigned int, + distanceToPreviousColliding, set_distanceToPreviousColliding ) + + + +} // namespace xAOD + +namespace xAOD { + + std::ostream& operator<<(std::ostream& s, const xAOD::FaserLHCData_v1& td) { + s << "xAODFaserLHCData: fill=" << td.fillNumber() + << " beamMode=" << td.beamMode() + << " betaStar=" << td.betaStar() + << " distanceToCollidingBCID=" << td.distanceToCollidingBCID() + << std::endl; + + return s; + } + +} // namespace xAOD diff --git a/xAOD/xAODFaserLHC/Root/xAODFaserLHCCLIDs.cxx b/xAOD/xAODFaserLHC/Root/xAODFaserLHCCLIDs.cxx new file mode 100644 index 0000000000000000000000000000000000000000..86811f0c3f95dc6b511ecfb2059561ea2b875c53 --- /dev/null +++ b/xAOD/xAODFaserLHC/Root/xAODFaserLHCCLIDs.cxx @@ -0,0 +1,8 @@ +/* + Copyright (C) 2020 CERN for the benefit of the FASER collaboration +*/ + +//simple includes to force the CLASS_DEF etc to be encountered during compile + +#include "xAODFaserLHC/FaserLHCData.h" +#include "xAODFaserLHC/FaserLHCDataAux.h" diff --git a/xAOD/xAODFaserLHC/xAODFaserLHC/FaserLHCData.h b/xAOD/xAODFaserLHC/xAODFaserLHC/FaserLHCData.h new file mode 100644 index 0000000000000000000000000000000000000000..561c8782ca68c12381928815f999d45264d73168 --- /dev/null +++ b/xAOD/xAODFaserLHC/xAODFaserLHC/FaserLHCData.h @@ -0,0 +1,22 @@ +// Dear emacs, this is -*- c++ -*- + +/* + Copyright (C) 2020 CERN for the benefit of the FASER collaboration +*/ + +#ifndef XAODFASERLHC_FASERLHCDATA_H +#define XAODFASERLHC_FASERLHCDATA_H + +// Local include(s): +#include "xAODFaserLHC/versions/FaserLHCData_v1.h" + +namespace xAOD { + /// Declare the latest version of the class + typedef FaserLHCData_v1 FaserLHCData; +} + +// Set up a CLID for the container: +#include "xAODCore/CLASS_DEF.h" +CLASS_DEF( xAOD::FaserLHCData, 255278152, 1 ) + +#endif // XAODFASERLHC_FASERLHCDATA_H diff --git a/xAOD/xAODFaserLHC/xAODFaserLHC/FaserLHCDataAux.h b/xAOD/xAODFaserLHC/xAODFaserLHC/FaserLHCDataAux.h new file mode 100644 index 0000000000000000000000000000000000000000..6eeac626679c0e95a000d01f96e436b8ad250eb6 --- /dev/null +++ b/xAOD/xAODFaserLHC/xAODFaserLHC/FaserLHCDataAux.h @@ -0,0 +1,22 @@ +// Dear emacs, this is -*- c++ -*- + +/* + Copyright (C) 2020 CERN for the benefit of the FASER collaboration +*/ + +#ifndef XAODFASERLHC_FASERLHCDATAAUX_H +#define XAODFASERLHC_FASERLHCDATAAUX_H + +// Local include(s): +#include "xAODFaserLHC/versions/FaserLHCDataAux_v1.h" + +namespace xAOD { + /// Declare the latest version of the class + typedef FaserLHCDataAux_v1 FaserLHCDataAux; +} + +// Set up a CLID for the container: +#include "xAODCore/CLASS_DEF.h" +CLASS_DEF( xAOD::FaserLHCDataAux, 151779941, 1 ) + +#endif // XAODFASERLHC_FASERLHCDATAAUX_H diff --git a/xAOD/xAODFaserLHC/xAODFaserLHC/selection.xml b/xAOD/xAODFaserLHC/xAODFaserLHC/selection.xml new file mode 100644 index 0000000000000000000000000000000000000000..c4ba39f9a6acad53d40208f74cb387ed89b3c36f --- /dev/null +++ b/xAOD/xAODFaserLHC/xAODFaserLHC/selection.xml @@ -0,0 +1,13 @@ +<!-- Copyright (C) 2020 CERN for the benefit of the FASER collaboration --> +<!-- Missing id values here, need to figure out where these come from... --> +<lcgdict> + + <class name="xAOD::FaserLHCData_v1" + id="6c373036-fad1-476c-9a8b-15591faccf00"/> + <typedef name="xAOD::FaserLHCData" /> + + <class name="xAOD::FaserLHCDataAux_v1" + id="484ef174-8efb-426a-888c-827f72ed972a"/> + <typedef name="xAOD::FaserLHCDataAux" /> + +</lcgdict> diff --git a/xAOD/xAODFaserLHC/xAODFaserLHC/versions/FaserLHCDataAux_v1.h b/xAOD/xAODFaserLHC/xAODFaserLHC/versions/FaserLHCDataAux_v1.h new file mode 100644 index 0000000000000000000000000000000000000000..bc1034143f4338ba39403ea82a7dde8561c636e7 --- /dev/null +++ b/xAOD/xAODFaserLHC/xAODFaserLHC/versions/FaserLHCDataAux_v1.h @@ -0,0 +1,74 @@ +// Dear emacs, this is -*- c++ -*- + +/* + Copyright (C) 2020 CERN for the benefit of the FASER collaboration +*/ + +#ifndef XAODFASERLHC_VERSIONS_FASERLHCDATAAUX_V1_H +#define XAODFASERLHC_VERSIONS_FASERLHCDATAAUX_V1_H + +// System include(s): +extern "C" { +# include "stdint.h" +} + +// xAOD include(s): +#include "xAODCore/AuxInfoBase.h" + +namespace xAOD { + + /// Class holding the data handled by FaserLHCData_v1 + /// + /// This class holds the payload of the TLB raw data + /// + /// @author Eric Torrence <torrence@uoregon.edu> + /// + /// $Revision: $ + /// $Date: $ + + class FaserLHCDataAux_v1 : public AuxInfoBase { + + public: + /// Default constructor + FaserLHCDataAux_v1(); + + private: + /// @name LHCData payload + /// @{ + unsigned int fillNumber; + std::string machineMode; + std::string beamMode; + int beamType1; + int beamType2; + + float betaStar; + float crossingAngle; + + bool stableBeams; + std::string injectionScheme; + + unsigned int numBunchBeam1; + unsigned int numBunchBeam2; + unsigned int numBunchColliding; + + int distanceToCollidingBCID; + int distanceToUnpairedB1; + int distanceToUnpairedB2; + int distanceToInboundB1; + + unsigned int distanceToTrainStart; + unsigned int distanceToPreviousColliding; + + /// @} + + }; // class FaserLHCDataAuxContainer_v1 + +} // namespace xAOD + +// Set up the StoreGate inheritance of the class: +#include "xAODCore/BaseInfo.h" +SG_BASE( xAOD::FaserLHCDataAux_v1, xAOD::AuxInfoBase ); + +#endif // XAODFASERLHC_VERSIONS_FASERLHCDATAAUX_V1_H + + diff --git a/xAOD/xAODFaserLHC/xAODFaserLHC/versions/FaserLHCData_v1.h b/xAOD/xAODFaserLHC/xAODFaserLHC/versions/FaserLHCData_v1.h new file mode 100644 index 0000000000000000000000000000000000000000..fd6c68cc0545bc8e5f06c92fb5abb288d9ce4e9f --- /dev/null +++ b/xAOD/xAODFaserLHC/xAODFaserLHC/versions/FaserLHCData_v1.h @@ -0,0 +1,127 @@ +// Dear emacs, this is -*- c++ -*- + +/* + Copyright (C) 2020 CERN for the benefit of the FASER collaboration +*/ + +#ifndef XAODFASERLHC_VERSIONS_FASERLHCDATA_V1_H +#define XAODFASERLHC_VERSIONS_FASERLHCDATA_V1_H + +// System include(s): +extern "C" { +# include "stdint.h" +} + +// Core EDM include(s): +#include "AthContainers/AuxElement.h" + +namespace xAOD { + + /// Class describing the Faser LHC information + /// + /// + class FaserLHCData_v1 : public SG::AuxElement { + + public: + /// Default constructor + FaserLHCData_v1(); + + /// @name Access LHC elements + /// @{ + + /// First batch comes from ATLAS /LHC/DCS/FILLSTATE folder + /// which is a copy of information sent to ATLAS by LHC over DIP + /// This is from the FASER COOL folder /LHC/BeamData + + /// LHC fill number + unsigned int fillNumber() const; + void set_fillNumber(unsigned int value); + + /// LHC machine mode (i.e. PROTON PHYSICS) + std::string machineMode() const; + void set_machineMode(std::string value); + + /// LHC Beam Mode (i.e. STABLE BEAMS) + std::string beamMode() const; + void set_beamMode(std::string value); + + /// LHC Beam type (charge of particle, 1-proton, 82-lead) + int beamType1() const; + void set_beamType1(int value); + + int beamType2() const; + void set_beamType2(int value); + + // Beta* at IP1, in cm + float betaStar() const; + void set_betaStar(float value); + + // Crossing angle at IP1, in uRad + float crossingAngle() const; + void set_crossingAngle(float value); + + // LHC stable beam flag + bool stableBeams() const; + void set_stableBeams(bool value); + + // Injection scheme + std::string injectionScheme() const; + void set_injectionScheme(std::string value); + + // Second batch is information is related to the BCID structure + // This comes from the LPC filling scheme (nominal values) + // and is stored in /LHC/BCIDData + + /// Nominal bunches (derived from DIP "Circulating Bunch Configuration") + unsigned int numBunchBeam1() const; + void set_numBunchBeam1(unsigned int value); + unsigned int numBunchBeam2() const; + void set_numBunchBeam2(unsigned int value); + unsigned int numBunchColliding() const; + void set_numBunchColliding(unsigned int value); + + // Number of BCIDs difference between current event BCID (from EventInfo) + // and a colliding BCID in the nominal bunch pattern + + int distanceToCollidingBCID() const; + void set_distanceToCollidingBCID(int value); + + int distanceToUnpairedB1() const; + void set_distanceToUnpairedB1(int value); + + int distanceToUnpairedB2() const; + void set_distanceToUnpairedB2(int value); + + int distanceToInboundB1() const; + void set_distanceToInboundB1(int value); + + /// Distance of current BCID to start of previous bunch train + unsigned int distanceToTrainStart() const; + void set_distanceToTrainStart(unsigned int value); + + /// Distance of current BCID frmo previous colliding BCID (0 if this is colliding) + unsigned int distanceToPreviousColliding() const; + void set_distanceToPreviousColliding(unsigned int value); + + /// Simple boolean functions to access useful values + /// In most cases, these check that the distance above is zero + bool isStable() const { return this->stableBeams(); } + bool isColliding() const { return this->distanceToCollidingBCID() == 0; } + bool isUnpairedBeam1() const { return this->distanceToUnpairedB1() == 0; } + bool isUnpairedBeam2() const { return this->distanceToUnpairedB2() == 0; } + bool isInboundBeam1() const { return this->distanceToInboundB1() == 0; } + + /// @} + + + }; // class FaserLHCData_v1 + + std::ostream& operator<<(std::ostream& s, const xAOD::FaserLHCData_v1& td); + +} // namespace xAOD + +// Declare the inheritance of the type: +#include "xAODCore/BaseInfo.h" +SG_BASE( xAOD::FaserLHCData_v1, SG::AuxElement ); + +#endif // XAODFASERLHC_VERSIONS_FASERLHCDATA_V1_H diff --git a/xAOD/xAODFaserLHC/xAODFaserLHC/xAODFaserLHCDict.h b/xAOD/xAODFaserLHC/xAODFaserLHC/xAODFaserLHCDict.h new file mode 100644 index 0000000000000000000000000000000000000000..4715ad862918741fd85966378b821f18229ac66a --- /dev/null +++ b/xAOD/xAODFaserLHC/xAODFaserLHC/xAODFaserLHCDict.h @@ -0,0 +1,27 @@ +/* + Copyright (C) 2020 CERN for the benefit of the FASER collaboration +*/ + +#ifndef XAODFASERLHC_XAODFASERLHCDICT_H +#define XAODFASERLHC_XAODFASERLHCDICT_H + +// Local include(s): +#include "xAODFaserLHC/FaserLHCData.h" +#include "xAODFaserLHC/FaserLHCDataAux.h" +#include "xAODFaserLHC/versions/FaserLHCData_v1.h" +#include "xAODFaserLHC/versions/FaserLHCDataAux_v1.h" + +// EDM include(s). +#include "xAODCore/tools/DictHelpers.h" + +namespace { + struct GCCXML_DUMMY_INSTANTIATION_XAODFASERLHC { + // Local type(s). + XAOD_INSTANTIATE_NS_OBJECT_TYPES( xAOD, FaserLHCData_v1 ); + + }; +} + + +#endif // XAODFASERLHC_XAODFASERLHCDICT_H + diff --git a/xAOD/xAODFaserLHCAthenaPool/CMakeLists.txt b/xAOD/xAODFaserLHCAthenaPool/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..d15a49ccdcaeb1312417a6b0834eadb395296169 --- /dev/null +++ b/xAOD/xAODFaserLHCAthenaPool/CMakeLists.txt @@ -0,0 +1,14 @@ +# Copyright (C) 2020 CERN for the benefit of the FASER collaboration + +# Declare the package name. +atlas_subdir( xAODFaserLHCAthenaPool ) + +# Component(s) in the package: +atlas_add_poolcnv_library( xAODFaserLHCAthenaPoolPoolCnv + src/*.h src/*.cxx + FILES xAODFaserLHC/FaserLHCData.h xAODFaserLHC/FaserLHCDataAux.h + TYPES_WITH_NAMESPACE xAOD::FaserLHCData xAOD::FaserLHCDataAux + CNV_PFX xAOD + LINK_LIBRARIES AthenaPoolCnvSvcLib AthenaPoolUtilities xAODFaserLHC ) + + diff --git a/xAOD/xAODFaserLHCAthenaPool/src/xAODFaserLHCDataAuxCnv.cxx b/xAOD/xAODFaserLHCAthenaPool/src/xAODFaserLHCDataAuxCnv.cxx new file mode 100644 index 0000000000000000000000000000000000000000..2ae9467033ddabd5b6c0e0fab94a5fb20c9c99de --- /dev/null +++ b/xAOD/xAODFaserLHCAthenaPool/src/xAODFaserLHCDataAuxCnv.cxx @@ -0,0 +1,5 @@ +/* + Copyright (C) 2020 CERN for the benefit of the FASER collaboration +*/ + +// Dummy source file so that cmake will know this is a custom converter. diff --git a/xAOD/xAODFaserLHCAthenaPool/src/xAODFaserLHCDataAuxCnv.h b/xAOD/xAODFaserLHCAthenaPool/src/xAODFaserLHCDataAuxCnv.h new file mode 100644 index 0000000000000000000000000000000000000000..dc3f3f9afc0e6cf99a6348eef0dc5bc3b1764501 --- /dev/null +++ b/xAOD/xAODFaserLHCAthenaPool/src/xAODFaserLHCDataAuxCnv.h @@ -0,0 +1,16 @@ +// Dear emacs, this is -*- c++ -*- + +/* + Copyright (C) 2020 CERN for the benefit of the FASER collaboration +*/ + +#ifndef XAODFASERLHCDATAATHENAPOOL_XAODFASERLHCDATAAUXCNV_H +#define XAODFASERLHCDATAATHENAPOOL_XAODFASERLHCDATAAUXCNV_H + +#include "xAODFaserLHC/FaserLHCDataAux.h" +#include "AthenaPoolCnvSvc/T_AthenaPoolAuxContainerCnv.h" + +typedef T_AthenaPoolAuxContainerCnv<xAOD::FaserLHCDataAux> xAODFaserLHCDataAuxCnv; + + +#endif // XAODFASERLHCDATAATHENAPOOL_XAODFASERLHCDATAAUXCNV_H diff --git a/xAOD/xAODFaserLHCAthenaPool/src/xAODFaserLHCDataCnv.cxx b/xAOD/xAODFaserLHCAthenaPool/src/xAODFaserLHCDataCnv.cxx new file mode 100644 index 0000000000000000000000000000000000000000..2ae9467033ddabd5b6c0e0fab94a5fb20c9c99de --- /dev/null +++ b/xAOD/xAODFaserLHCAthenaPool/src/xAODFaserLHCDataCnv.cxx @@ -0,0 +1,5 @@ +/* + Copyright (C) 2020 CERN for the benefit of the FASER collaboration +*/ + +// Dummy source file so that cmake will know this is a custom converter. diff --git a/xAOD/xAODFaserLHCAthenaPool/src/xAODFaserLHCDataCnv.h b/xAOD/xAODFaserLHCAthenaPool/src/xAODFaserLHCDataCnv.h new file mode 100644 index 0000000000000000000000000000000000000000..a73c439c688c0ef5879a84cd300ab15622d45c5e --- /dev/null +++ b/xAOD/xAODFaserLHCAthenaPool/src/xAODFaserLHCDataCnv.h @@ -0,0 +1,17 @@ +// Dear emacs, this is -*- c++ -*- + +/* + Copyright (C) 2020 CERN for the benefit of the FASER collaboration +*/ + +#ifndef XAODFASERLHCDATAATHENAPOOL_XAODFASERLHCDATACNV_H +#define XAODFASERLHCDATAATHENAPOOL_XAODFASERLHCDATACNV_H + +#include "xAODFaserLHC/FaserLHCData.h" +#include "AthenaPoolCnvSvc/T_AthenaPoolxAODCnv.h" + + +typedef T_AthenaPoolxAODCnv<xAOD::FaserLHCData> xAODFaserLHCDataCnv; + + +#endif // XAODFASERLHCDATAATHENAPOOL_XAODFASERLHCDATACNV_H