diff --git a/TileCalorimeter/TileMonitoring/CMakeLists.txt b/TileCalorimeter/TileMonitoring/CMakeLists.txt index 63fa307b2d3212f157038132d79a917f295de7fb..c2ef7632ef60f0c1a6a7098c86642cbf36a4f19d 100644 --- a/TileCalorimeter/TileMonitoring/CMakeLists.txt +++ b/TileCalorimeter/TileMonitoring/CMakeLists.txt @@ -89,6 +89,11 @@ atlas_add_test( TileMuonFitMonitorAlgorithm_test PROPERTIES TIMEOUT 600 POST_EXEC_SCRIPT nopost.sh) +atlas_add_test( TileRODMonitorAlgorithm_test + SCRIPT python -m TileMonitoring.TileRODMonitorAlgorithm + PROPERTIES TIMEOUT 600 + POST_EXEC_SCRIPT nopost.sh) + atlas_add_test( TileMonitoringConfig_test SCRIPT python -m TileMonitoring.TileMonitoringConfig PROPERTIES TIMEOUT 300 diff --git a/TileCalorimeter/TileMonitoring/python/TileMuIdMonitorAlgorithm.py b/TileCalorimeter/TileMonitoring/python/TileMuIdMonitorAlgorithm.py index e63686d0163f1f106c0974aec14d1c0ef69eef1e..ed69925e3d4c6dc85cf81a57b89308132eecfdda 100644 --- a/TileCalorimeter/TileMonitoring/python/TileMuIdMonitorAlgorithm.py +++ b/TileCalorimeter/TileMonitoring/python/TileMuIdMonitorAlgorithm.py @@ -1,5 +1,5 @@ # -# Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration # ''' @file TileMuIdMonitorAlgorithm.py @@ -14,6 +14,12 @@ def TileMuIdMonitoringConfig(flags, **kwargs): from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator result = ComponentAccumulator() + from TileGeoModel.TileGMConfig import TileGMCfg + result.merge(TileGMCfg(flags)) + + from LArGeoAlgsNV.LArGMConfig import LArGMCfg + result.merge(LArGMCfg(flags)) + # The following class will make a sequence, configure algorithms, and link # them to GenericMonitoringTools from AthenaMonitoring import AthMonitorCfgHelper diff --git a/TileCalorimeter/TileMonitoring/python/TileRODMonitorAlgorithm.py b/TileCalorimeter/TileMonitoring/python/TileRODMonitorAlgorithm.py new file mode 100644 index 0000000000000000000000000000000000000000..fcaf3497604c8d0a7da837072fdea1c9b99b60b9 --- /dev/null +++ b/TileCalorimeter/TileMonitoring/python/TileRODMonitorAlgorithm.py @@ -0,0 +1,215 @@ +# +# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +# +''' +@file TileRODMonitorAlgorithm.py +@brief Python configuration of TileRODMonitorAlgorithm algorithm for the Run III +''' + +def TileRODMonitoringConfig(flags, **kwargs): + ''' Function to configure TileRODMonitorAlgorithm algorithm in the monitoring system.''' + + # Define one top-level monitoring algorithm. The new configuration + # framework uses a component accumulator. + from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator + result = ComponentAccumulator() + + from TileRecUtils.TileDQstatusConfig import TileDQstatusAlgCfg + result.merge( TileDQstatusAlgCfg(flags) ) + + from TileGeoModel.TileGMConfig import TileGMCfg + result.merge(TileGMCfg(flags)) + + from TileConditions.TileCablingSvcConfig import TileCablingSvcCfg + result.merge( TileCablingSvcCfg(flags) ) + + from TileConditions.TileBadChannelsConfig import TileBadChannelsCondAlgCfg + result.merge( TileBadChannelsCondAlgCfg(flags, **kwargs) ) + + kwargs.setdefault('CheckDCS', flags.Tile.useDCS) + if kwargs['CheckDCS']: + from TileConditions.TileDCSConfig import TileDCSCondAlgCfg + result.merge( TileDCSCondAlgCfg(flags) ) + + from AthenaConfiguration.ComponentFactory import CompFactory + + kwargs.setdefault('fillRODFragmentSizeHistograms', True) + fillRODFragmentSizeHistograms = kwargs['fillRODFragmentSizeHistograms'] + if fillRODFragmentSizeHistograms: + result.addService(CompFactory.ROBDataProviderSvc()) + + # The following class will make a sequence, configure algorithms, and link + # them to GenericMonitoringTools + from AthenaMonitoring import AthMonitorCfgHelper + helper = AthMonitorCfgHelper(flags,'TileRODMonitoring') + + # Adding an TileRODMonitorAlgorithm algorithm to the helper + tileRODMonAlg = helper.addAlgorithm(CompFactory.TileRODMonitorAlgorithm, 'TileRODMonAlg') + + # L1Trigger Type Bits: + # bit0_RNDM, bit1_ZeroBias, bit2_L1Cal, bit3_Muon, + # bit4_RPC, bit5_FTK, bit6_CTP, bit7_Calib, AnyPhysTrig + kwargs.setdefault('fillHistogramsForL1Triggers', ['AnyPhysTrig', 'bit7_Calib']) + l1Triggers = kwargs['fillHistogramsForL1Triggers'] + + kwargs.setdefault('EnergyThreshold', 300.) + energyThreshold = kwargs['EnergyThreshold'] + + kwargs.setdefault('TileRawChannelContainer', flags.Tile.RawChannelContainer) + kwargs.setdefault('NumberOfROBFragmets', 32) + nROBs = kwargs['NumberOfROBFragmets'] + + for k, v in kwargs.items(): + setattr(tileRODMonAlg, k, v) + + run = str(flags.Input.RunNumber[0]) + + # Configure histogram with TileRODMonAlg algorithm execution time + executeTimeGroup = helper.addGroup(tileRODMonAlg, 'TileRODMonExecuteTime', 'Tile/') + executeTimeGroup.defineHistogram('TIME_execute', path = 'ROD', type='TH1F', + title = 'Time for execute TileRODMonAlg algorithm;time [#ms]', + xbins = 100, xmin = 0, xmax = 100000) + + + from TileMonitoring.TileMonitoringCfgHelper import addTile1DHistogramsArray + + # Configure histograms with relative difference between Tile DSP and offline energies + titleEnergyDiff = 'Relative difference between E_{DSP} and E_{OFFLINE}' + titleEnergyDiff += ';(E_{DSP}- E_{OFFLINE})/E_{OFFLINE}' + addTile1DHistogramsArray(helper, tileRODMonAlg, name = 'TileDspEnergyDiff', + xvalue = 'energyDiff', title = titleEnergyDiff, path = 'Tile/ROD', + xbins = 41, xmin = -0.205, xmax = 0.205, type = 'TH1D', run = run, + triggers = l1Triggers, perPartition = True) + + # Configure histograms with difference between Tile DSP and offline times + titleTimeDiff = 'Difference between t_{DSP} and t_{OFFLINE}' + titleTimeDiff += ';t_{DSP}- t_{OFFLINE} [ns]' + addTile1DHistogramsArray(helper, tileRODMonAlg, name = 'TileDspTimeDiff', + xvalue = 'timeDiff', title = titleTimeDiff, path = 'Tile/ROD', + xbins = 101, xmin = -50.5, xmax = 50.5, type = 'TH1D', run = run, + triggers = l1Triggers, perPartition = True) + + # Configure histograms with difference between Tile DSP and offline times vs offline time + titleTimeDiffVsTime = 'Difference between t_{DSP} and t_{OFFLINE}' + titleTimeDiffVsTime += ';t_{OFFLINE} [ns];t_{DSP}- t_{OFFLINE} [ns]' + addTile1DHistogramsArray(helper, tileRODMonAlg, name = 'TileDspTimeDiffVsTime', + xvalue = 'time', value = 'timeDiff', title = titleTimeDiffVsTime, + path = 'Tile/ROD', xbins = 51, xmin = -25.5, xmax = 25.5, + type = 'TProfile', run = run, triggers = l1Triggers, perPartition = True) + + # Configure histograms with difference between Tile DSP and offline times vs offline energy + titleTimeDiffVsEnergy = 'Difference between t_{DSP} and t_{OFFLINE}' + titleTimeDiffVsEnergy += ';E_{OFFLINE} [MeV];t_{DSP}- t_{OFFLINE}' + addTile1DHistogramsArray(helper, tileRODMonAlg, name = 'TileDspTimeDiffVsEnergy', + xvalue = 'energy', value = 'timeDiff', title = titleTimeDiffVsEnergy, + path = 'Tile/ROD', xbins = 75, xmin = energyThreshold, xmax = 15000., + type = 'TProfile', run = run, triggers = l1Triggers, perPartition = True) + + + from TileMonitoring.TileMonitoringCfgHelper import addTile2DHistogramsArray + + # Configure histograms with relative difference between Tile DSP and offline energies vs offline time + titleEnergyDiffVsTime = 'Relative difference between E_{DSP} and E_{OFFLINE}' + titleEnergyDiffVsTime += ';t_{DSP} [ns];(E_{DSP}- E_{OFFLINE})/E_{OFFLINE}' + addTile2DHistogramsArray(helper, tileRODMonAlg, name = 'TileDspEnergyDiffVsTime', + xvalue = 'time', yvalue = 'energyDiff', + title = titleEnergyDiffVsTime, path = 'Tile/ROD', + xbins = 51, xmin = -25.5, xmax = 25.5, + ybins = 30, ymin = -0.35, ymax = 0.1, + type = 'TH2D', run = run, triggers = l1Triggers, perPartition = True) + + # Configure histograms with relative difference between Tile DSP and offline energies vs offline energy + titleEnergyDiffVsEnergy = 'Relative difference between E_{DSP} and E_{OFFLINE}' + titleEnergyDiffVsEnergy += ';E_{OFFLINE} [MeV];(E_{DSP}- E_{OFFLINE})/E_{OFFLINE}' + addTile2DHistogramsArray(helper, tileRODMonAlg, name = 'TileDspEnergyDiffVsEnergy', + xvalue = 'energy', yvalue = 'energyDiff', + title = titleEnergyDiffVsEnergy, path = 'Tile/ROD', + xbins = 75, xmin = energyThreshold, xmax = 15000., + ybins = 82, ymin = -0.205, ymax = 0.205, + type = 'TH2D', run = run, triggers = l1Triggers, perPartition = True) + + + from TileMonitoring.TileMonitoringCfgHelper import addTileModuleChannelMapsArray + + # Configure histograms with everagy Tile channel time per partition + titleChanTime = ('Tile DSP Channel Time (t_{DSP}) [ns], E_{ch} > %s MeV' % energyThreshold) + addTileModuleChannelMapsArray(helper, tileRODMonAlg, name = 'TileDspChannelTime', type = 'TProfile2D', + value = 'time', title = titleChanTime, path = 'Tile/ROD', + run = run, triggers = l1Triggers, separator = '_') + + + if fillRODFragmentSizeHistograms: + # Configure histogram with all Tile ROD fragments size vs luminosity block + titleAllRodFragSize = 'All Tile ROD fragments size vs luminosity block;LumiBlock;# words' + addTile1DHistogramsArray(helper, tileRODMonAlg, name = 'TileRodFragmentSizeLB', + xvalue = 'lumiBlock', value = 'allRodFragsSize', + title = titleAllRodFragSize, path = 'Tile/ROD', + xbins = 1000, xmin = -0.5, xmax = 999.5, + type = 'TProfile', run = run, triggers = l1Triggers, + perPartition = False, opt = 'kAddBinsDynamically') + + from TileCalibBlobObjs.Classes import TileCalibUtils as Tile + from TileMonitoring.TileMonitoringCfgHelper import getPartitionName + + # Configure histogram with Tile ROD fragment size vs fragment number and partition + titleRodFragSize = 'Tile ROD fragment size [word]; Fragment;' + partitionLabels = [getPartitionName(ros) for ros in range(1, Tile.MAX_ROS)] + addTile2DHistogramsArray(helper, tileRODMonAlg, name = 'TileRodFragmentMapSize', + xvalue = 'fragment', yvalue = 'partition', value = 'rodFragSize', + title = titleRodFragSize, path = 'Tile/ROD', + xbins = nROBs, xmin = -0.5, xmax = nROBs - 0.5, + ybins = Tile.MAX_ROS - 1, ymin = 0.5, ymax = Tile.MAX_ROS - 0.5, + type = 'TProfile2D', run = run, triggers = l1Triggers, ylabels = partitionLabels) + + + accumalator = helper.result() + result.merge(accumalator) + return result + +if __name__=='__main__': + + # Setup the Run III behavior + from AthenaCommon.Configurable import Configurable + Configurable.configurableRun3Behavior = True + + # Setup logs + from AthenaCommon.Logging import log + from AthenaCommon.Constants import INFO + log.setLevel(INFO) + + # Set the Athena configuration flags + from AthenaConfiguration.AllConfigFlags import ConfigFlags + + from AthenaConfiguration.TestDefaults import defaultTestFiles + ConfigFlags.Input.Files = defaultTestFiles.RAW + ConfigFlags.Output.HISTFileName = 'TileRODMonitorOutput.root' + ConfigFlags.DQ.useTrigger = False + ConfigFlags.DQ.enableLumiAccess = False + ConfigFlags.Tile.doOptATLAS = True + ConfigFlags.Exec.MaxEvents = 3 + ConfigFlags.fillFromArgs() + ConfigFlags.lock() + + # Initialize configuration object, add accumulator, merge, and run. + from AthenaConfiguration.MainServicesConfig import MainServicesCfg + cfg = MainServicesCfg(ConfigFlags) + + from ByteStreamCnvSvc.ByteStreamConfig import ByteStreamReadCfg + tileTypeNames = ['TileRawChannelContainer/TileRawChannelCnt', 'TileDigitsContainer/TileDigitsCnt'] + cfg.merge( ByteStreamReadCfg(ConfigFlags, type_names = tileTypeNames) ) + + from TileRecUtils.TileRawChannelMakerConfig import TileRawChannelMakerCfg + cfg.merge( TileRawChannelMakerCfg(ConfigFlags) ) + + cfg.merge( TileRODMonitoringConfig(ConfigFlags) ) + + cfg.printConfig(withDetails = True, summariseProps = True) + ConfigFlags.dump() + + cfg.store( open('TileRODMonitorAlgorithm.pkl','wb') ) + + sc = cfg.run() + + import sys + # Success should be 0 + sys.exit(not sc.isSuccess()) diff --git a/TileCalorimeter/TileMonitoring/src/TileRODMonitorAlgorithm.cxx b/TileCalorimeter/TileMonitoring/src/TileRODMonitorAlgorithm.cxx new file mode 100644 index 0000000000000000000000000000000000000000..663ce8b9fe92c2251ab78b491817174e4cff305c --- /dev/null +++ b/TileCalorimeter/TileMonitoring/src/TileRODMonitorAlgorithm.cxx @@ -0,0 +1,333 @@ +/* + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ + +#include "TileRODMonitorAlgorithm.h" +#include "TileIdentifier/TileHWID.h" +#include "TileCalibBlobObjs/TileCalibUtils.h" + +#include "StoreGate/ReadHandle.h" +#include "StoreGate/ReadCondHandle.h" + +StatusCode TileRODMonitorAlgorithm::initialize() { + + ATH_MSG_DEBUG("in initialize()"); + + // initialize superclass + ATH_CHECK( TileMonitorAlgorithm::initialize() ); + + std::sort(m_fragIDsToIgnoreDMUerrors.begin(), m_fragIDsToIgnoreDMUerrors.end()); + + ATH_CHECK( detStore()->retrieve(m_tileHWID) ); + + ATH_CHECK( m_cablingSvc.retrieve() ); + m_cabling = m_cablingSvc->cablingService(); + + ATH_CHECK( m_rawChannelContainerKey.initialize() ); + ATH_CHECK( m_dspRawChannelContainerKey.initialize() ); + ATH_CHECK( m_DQstatusKey.initialize() ); + ATH_CHECK( m_badChannelsKey.initialize() ); + ATH_CHECK( m_emScaleKey.initialize() ); + ATH_CHECK( m_DCSStateKey.initialize(m_checkDCS) ); + + if (m_comparisonUnit <= TileRawChannelUnit::OnlineMegaElectronVolts) { + m_finalRawChannelUnit = static_cast<TileRawChannelUnit::UNIT>(m_comparisonUnit.value()); + } + + if (m_timeRange.size() != 2) { + ATH_MSG_FATAL( "Size of TimeRange should be 2 (from,to), but is " << m_timeRange.size() ); + return StatusCode::FAILURE; + } + + using namespace Monitored; + using Tile = TileCalibUtils; + + int nL1Triggers = getNumberOfL1Triggers(); + + m_energyDiffGroups = buildToolMap<std::vector<int>>(m_tools, "TileDspEnergyDiff", + Tile::MAX_ROS - 1, nL1Triggers); + + m_energyDiffVsTimeGroups = buildToolMap<std::vector<int>>(m_tools, "TileDspEnergyDiffVsTime", + Tile::MAX_ROS - 1, nL1Triggers); + + m_energyDiffVsEnergyGroups = buildToolMap<std::vector<int>>(m_tools, "TileDspEnergyDiffVsEnergy", + Tile::MAX_ROS - 1, nL1Triggers); + + m_timeDiffGroups = buildToolMap<std::vector<int>>(m_tools, "TileDspTimeDiff", + Tile::MAX_ROS - 1, nL1Triggers); + + m_timeDiffVsTimeGroups = buildToolMap<std::vector<int>>(m_tools, "TileDspTimeDiffVsTime", + Tile::MAX_ROS - 1, nL1Triggers); + + m_timeDiffVsEnergyGroups = buildToolMap<std::vector<int>>(m_tools, "TileDspTimeDiffVsEnergy", + Tile::MAX_ROS - 1, nL1Triggers); + + m_dspChanTimeGroups = buildToolMap<std::vector<int>>(m_tools, "TileDspChannelTime", + Tile::MAX_ROS - 1, nL1Triggers); + + if (m_fillRODfragSizeHistograms) { + ATH_CHECK( m_robSvc.retrieve() ); + + if (m_nROBs > MAX_TILE_ROBS) { + int nROBsSetUp = m_nROBs; + m_nROBs = MAX_TILE_ROBS; + ATH_MSG_INFO( "Decreasing number of ROBs from " << nROBsSetUp << " to " << m_nROBs ); + } + + m_tileRobIds.reserve((Tile::MAX_ROS - 1) * m_nROBs); // Partitions * fragments + for (unsigned int rodId : {0x510000, 0x520000, 0x530000, 0x540000}) { + for (unsigned int fragment = 0; fragment < m_nROBs; ++fragment) { + m_tileRobIds.push_back(rodId + fragment); + } + } + + m_rodFragSizeMapGroups = buildToolMap<int>(m_tools, "TileRodFragmentMapSize", nL1Triggers); + m_rodFragSizeLBGroups = buildToolMap<int>(m_tools, "TileRodFragmentSizeLB", nL1Triggers); + } + + return StatusCode::SUCCESS; +} + + +StatusCode TileRODMonitorAlgorithm::fillHistograms( const EventContext& ctx ) const { + + using Tile = TileCalibUtils; + + // In case you want to measure the execution time + auto timer = Monitored::Timer("TIME_execute"); + + const xAOD::EventInfo* eventInfo = GetEventInfo(ctx).get(); + + ATH_MSG_DEBUG(*eventInfo); + + const TileDQstatus* dqStatus = SG::makeHandle(m_DQstatusKey, ctx).get(); + const TileDCSState* dcsState = m_checkDCS ? SG::ReadCondHandle(m_DCSStateKey, ctx).cptr() : nullptr; + + SG::ReadCondHandle<TileBadChannels> badChannels(m_badChannelsKey, ctx); + SG::ReadCondHandle<TileEMScale> emScale(m_emScaleKey, ctx); + + SG::ReadHandle<TileRawChannelContainer> rawChannelContainer(m_rawChannelContainerKey, ctx); + ATH_CHECK( rawChannelContainer.isValid() ); + + TileRawChannelUnit::UNIT rawChannelUnit = rawChannelContainer->get_unit(); + + float referenceTimes[Tile::MAX_ROS - 1][Tile::MAX_DRAWER][Tile::MAX_CHAN] = {{{0}}}; + float referenceEnergies[Tile::MAX_ROS - 1][Tile::MAX_DRAWER][Tile::MAX_CHAN] = {{{0}}}; + + for (const TileRawChannelCollection* rawChannelCollection : *rawChannelContainer) { + if (rawChannelCollection->empty() ) continue; + + HWIdentifier adc_id = rawChannelCollection->front()->adc_HWID(); + int ros = m_tileHWID->ros(adc_id); + int drawer = m_tileHWID->drawer(adc_id); + unsigned int drawerIdx = TileCalibUtils::getDrawerIdx(ros, drawer); + int partition = ros - 1; + + bool checkDQ = true; + + int fragId = rawChannelCollection->identify(); + if (std::binary_search(m_fragIDsToIgnoreDMUerrors.begin(), m_fragIDsToIgnoreDMUerrors.end(), fragId)) { + checkDQ = false; + } + + for (const TileRawChannel* rawChannel : *rawChannelCollection) { + + adc_id = rawChannel->adc_HWID(); + int channel = m_tileHWID->channel(adc_id); + int adc = m_tileHWID->adc(adc_id); + + if (m_cabling->isDisconnected(ros, drawer, channel)) { + ATH_MSG_VERBOSE(m_tileHWID->to_string(adc_id) << ": channlel is disconnected => skipping!"); + continue; + } + + if (checkDQ && !(dqStatus->isAdcDQgood(ros, drawer, channel, adc))) { + ATH_MSG_VERBOSE(m_tileHWID->to_string(adc_id) << ": DQ is BAD => skipping!"); + continue; + } + + if (m_checkDCS && dcsState->isStatusBad(ros, drawer, channel)) { + ATH_MSG_VERBOSE(m_tileHWID->to_string(adc_id) << ": DCS is Bad => skipping!"); + continue; + } + + if (badChannels->getAdcStatus(adc_id).isBad()) { + ATH_MSG_VERBOSE(m_tileHWID->to_string(adc_id) << ": Status is BAD => skipping!"); + continue; + } + + if (ros > 2) { // Check if channel is MBTS, no MBTS in LB + int pmt; + int index; + m_cabling->h2s_cell_id_index(adc_id, index, pmt); + if (index < -1) { + ATH_MSG_VERBOSE(m_tileHWID->to_string(adc_id) << ": MBTS => skipping!"); + continue; + } + } + + float amplitude = rawChannel->amplitude(); + if (rawChannelUnit != m_comparisonUnit) { + amplitude = emScale->calibrateChannel(drawerIdx, channel, adc, amplitude, rawChannelUnit, m_finalRawChannelUnit); + } + + float time = rawChannel->uncorrTime(); + if (amplitude > m_energyThreshold && time > m_timeRange[0] && time < m_timeRange[1]) { + referenceEnergies[partition][drawer][channel] = amplitude; + referenceTimes[partition][drawer][channel] = time; + } + } + } + + std::vector<float> timeDiffs[Tile::MAX_ROS - 1]; + std::vector<float> energyDiffs[Tile::MAX_ROS - 1]; + std::vector<float> offlineEnergies[Tile::MAX_ROS - 1]; + std::vector<float> offlineTimes[Tile::MAX_ROS - 1]; + + std::vector<float> dspTimes[Tile::MAX_ROS - 1]; + std::vector<float> dspTimesChannels[Tile::MAX_ROS - 1]; + std::vector<float> dspTimesDrawers[Tile::MAX_ROS - 1]; + + SG::ReadHandle<TileRawChannelContainer> dspRawChannelContainer(m_dspRawChannelContainerKey, ctx); + ATH_CHECK( dspRawChannelContainer.isValid() ); + + TileRawChannelUnit::UNIT dspRawChannelUnit = dspRawChannelContainer->get_unit(); + for (const TileRawChannelCollection* rawChannelCollection : *dspRawChannelContainer) { + if (rawChannelCollection->empty() ) continue; + + HWIdentifier adc_id = rawChannelCollection->front()->adc_HWID(); + int ros = m_tileHWID->ros(adc_id); + int drawer = m_tileHWID->drawer(adc_id); + unsigned int drawerIdx = TileCalibUtils::getDrawerIdx(ros, drawer); + int partition = ros - 1; + + for (const TileRawChannel* rawChannel : *rawChannelCollection) { + adc_id = rawChannel->adc_HWID(); + int channel = m_tileHWID->channel(adc_id); + int adc = m_tileHWID->adc(adc_id); + + float offlineEnergy = referenceEnergies[partition][drawer][channel]; + if (offlineEnergy > m_energyThreshold) { + offlineEnergies[partition].push_back(offlineEnergy); + + float offlineTime = referenceTimes[partition][drawer][channel]; + offlineTimes[partition].push_back(offlineTime); + + float dspEnergy = rawChannel->amplitude(); + float dspTime = rawChannel->uncorrTime(); + dspTimes[partition].push_back(dspTime); + dspTimesDrawers[partition].push_back(drawer); + dspTimesChannels[partition].push_back(channel); + + if (dspRawChannelUnit != m_finalRawChannelUnit) { + dspEnergy = emScale->calibrateChannel(drawerIdx, channel, adc, dspEnergy, dspRawChannelUnit, m_finalRawChannelUnit); + } + + float energyDiff = (dspEnergy - offlineEnergy) / offlineEnergy; + energyDiffs[partition].push_back(energyDiff); + + float timeDiff = dspTime - offlineTime; + timeDiffs[partition].push_back(timeDiff); + + ATH_MSG_VERBOSE(m_tileHWID->to_string(adc_id) << ": (DSP/OFFLINE)" + << ", energy " << dspEnergy << "/" << offlineEnergy + << ", time " << dspTime << "/" << offlineTime); + } + } + } + + // Indices of L1 trigger histograms to be filled in the current event + std::vector<int> l1TriggersIndices = getL1TriggerIndices(eventInfo->level1TriggerType()); + + for (unsigned int partition = 0; partition < Tile::MAX_ROS - 1; ++partition) { + if (!energyDiffs[partition].empty()) { + auto monTime = Monitored::Collection("time", offlineTimes[partition]); + auto monEnergy = Monitored::Collection("energy", offlineEnergies[partition]); + auto monEnergyDiff = Monitored::Collection("energyDiff", energyDiffs[partition]); + for (int l1TriggerIdx : l1TriggersIndices) { + fill(m_tools[m_energyDiffGroups[partition][l1TriggerIdx]], monEnergyDiff); + fill(m_tools[m_energyDiffVsTimeGroups[partition][l1TriggerIdx]], monTime, monEnergyDiff); + fill(m_tools[m_energyDiffVsEnergyGroups[partition][l1TriggerIdx]], monEnergy, monEnergyDiff); + } + } + + if (!timeDiffs[partition].empty()) { + auto monTime = Monitored::Collection("time", offlineTimes[partition]); + auto monEnergy = Monitored::Collection("energy", offlineEnergies[partition]); + auto monTimeDiff = Monitored::Collection("timeDiff", timeDiffs[partition]); + for (int l1TriggerIdx : l1TriggersIndices) { + fill(m_tools[m_timeDiffGroups[partition][l1TriggerIdx]], monTimeDiff); + fill(m_tools[m_timeDiffVsTimeGroups[partition][l1TriggerIdx]], monTime, monTimeDiff); + fill(m_tools[m_timeDiffVsEnergyGroups[partition][l1TriggerIdx]], monEnergy, monTimeDiff); + } + } + if (!timeDiffs[partition].empty()) { + auto monTime = Monitored::Collection("time", offlineTimes[partition]); + auto monEnergy = Monitored::Collection("energy", offlineEnergies[partition]); + auto monTimeDiff = Monitored::Collection("timeDiff", timeDiffs[partition]); + for (int l1TriggerIdx : l1TriggersIndices) { + fill(m_tools[m_timeDiffGroups[partition][l1TriggerIdx]], monTimeDiff); + fill(m_tools[m_timeDiffVsTimeGroups[partition][l1TriggerIdx]], monTime, monTimeDiff); + fill(m_tools[m_timeDiffVsEnergyGroups[partition][l1TriggerIdx]], monEnergy, monTimeDiff); + } + } + + if (!dspTimes[partition].empty()) { + auto monTime = Monitored::Collection("time", dspTimes[partition]); + auto monModule = Monitored::Collection("module", dspTimesDrawers[partition]); + auto monChannel = Monitored::Collection("channel", dspTimesChannels[partition]); + for (int l1TriggerIdx : l1TriggersIndices) { + fill(m_tools[m_dspChanTimeGroups[partition][l1TriggerIdx]], monModule, monChannel, monTime); + } + } + + } + + + if (m_fillRODfragSizeHistograms) { + int allTileRodFragsSize = 0; + std::vector<int> roses; + std::vector<int> fragments; + std::vector<int> fragmentSizes; + + std::vector<const OFFLINE_FRAGMENTS_NAMESPACE::ROBFragment*> robFragments; + m_robSvc->getROBData(m_tileRobIds, robFragments); + + for (const OFFLINE_FRAGMENTS_NAMESPACE::ROBFragment* robFragment : robFragments) { + uint32_t rodSourceId = robFragment->rod_source_id(); + unsigned int ros = (rodSourceId & 0x0F0000) >> 16; + unsigned int fragment = rodSourceId & 0x0000FF; + int rodFragmentSize = robFragment->rod_fragment_size_word(); + + allTileRodFragsSize += rodFragmentSize; + if (ros > 0 && ros < Tile::MAX_ROS && fragment < m_nROBs) { + roses.push_back(ros); + fragments.push_back(fragment); + fragmentSizes.push_back(rodFragmentSize); + ATH_MSG_VERBOSE("ROS = " << ros << ", ROD fragment = " << fragment << ", size = " << rodFragmentSize); + } + } + + ATH_MSG_DEBUG( "All Tile ROD fragemsts size: " << allTileRodFragsSize << " in LB " << eventInfo->lumiBlock()); + + auto lumiBlock = Monitored::Scalar<int>("lumiBlock", eventInfo->lumiBlock()); + auto monRodFragsSize = Monitored::Scalar<int>("allRodFragsSize", allTileRodFragsSize); + for (int l1TriggerIdx : l1TriggersIndices) { + fill(m_tools[m_rodFragSizeLBGroups[l1TriggerIdx]], lumiBlock, monRodFragsSize); + } + + if (!fragmentSizes.empty()) { + auto monPartition = Monitored::Collection("partition", roses); + auto monFragment = Monitored::Collection("fragment", fragments); + auto monFragmentSize = Monitored::Collection("rodFragSize", fragmentSizes); + for (int l1TriggerIdx : l1TriggersIndices) { + fill(m_tools[m_rodFragSizeMapGroups[l1TriggerIdx]], monFragment, monPartition, monFragmentSize); + } + } + } + + + fill("TileRODMonExecuteTime", timer); + + return StatusCode::SUCCESS; +} diff --git a/TileCalorimeter/TileMonitoring/src/TileRODMonitorAlgorithm.h b/TileCalorimeter/TileMonitoring/src/TileRODMonitorAlgorithm.h new file mode 100644 index 0000000000000000000000000000000000000000..ad0c254dc53ff1af1ecd0dcd89c5482f0fc1d0c6 --- /dev/null +++ b/TileCalorimeter/TileMonitoring/src/TileRODMonitorAlgorithm.h @@ -0,0 +1,122 @@ +/* + Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TILEMONITORING_TILERODMONITORALGORITHM_H +#define TILEMONITORING_TILERODMONITORALGORITHM_H + +#include "TileEvent/TileDQstatus.h" +#include "TileIdentifier/TileRawChannelUnit.h" +#include "TileEvent/TileRawChannelContainer.h" +#include "TileConditions/TileDCSState.h" +#include "TileConditions/TileBadChannels.h" +#include "TileConditions/TileEMScale.h" +#include "TileConditions/TileCablingSvc.h" +#include "TileMonitorAlgorithm.h" + +#include "ByteStreamCnvSvcBase/IROBDataProviderSvc.h" +#include "AthenaMonitoringKernel/Monitored.h" +#include "StoreGate/ReadHandleKey.h" +#include "StoreGate/ReadCondHandleKey.h" + +class TileHWID; +class TileCablingService; + +/** @class TileRODMonitorAlgorithm + * @brief Class for Tile digi noise based monitoring + */ + +class TileRODMonitorAlgorithm : public TileMonitorAlgorithm { + + public: + + using TileMonitorAlgorithm::TileMonitorAlgorithm; + virtual ~TileRODMonitorAlgorithm() = default; + virtual StatusCode initialize() override; + virtual StatusCode fillHistograms(const EventContext& ctx) const override; + + private: + + Gaudi::Property<bool> m_checkDCS{this, "CheckDCS", false, "Check Tile DCS status"}; + Gaudi::Property<std::vector<unsigned int>> m_triggerTypes{this, + "TriggerTypes", {}, "Given trigger types only events with these TT will be used, otherwise all"}; + + Gaudi::Property<std::vector<int>> m_fragIDsToIgnoreDMUerrors{this, + "FragIDsToIgnoreDMUErrors", {}, "List of Tile frag IDs for which ignore DMU errors"}; + + Gaudi::Property<unsigned int> m_comparisonUnit{this, + "ComparisonUnit", TileRawChannelUnit::MegaElectronVolts, "Units to compare Tile raw channel containers"}; + + Gaudi::Property<float> m_energyThreshold{this, + "EnergyThreshold", 300.0F, "Energy threshold in MeV"}; + + Gaudi::Property<std::vector<float>> m_timeRange{this, + "TimeRange", {-65.0F, 65.0F}, "Time range to be monitored, default: (-65,65)"}; + + Gaudi::Property<unsigned int> m_nROBs{this, + "NumberOfROBFragmets", MAX_TILE_ROBS, "Number of Tile ROB fragments"}; + + Gaudi::Property<bool> m_fillRODfragSizeHistograms{this, + "fillRODFragmentSizeHistograms", true, "Fill summary histograms with ROD fragment size"}; + + SG::ReadHandleKey<TileDQstatus> m_DQstatusKey{this, + "TileDQstatus", "TileDQstatus", "Tile DQ status name"}; + + /** + * @brief Name of TileDCSState object in condition store + */ + SG::ReadCondHandleKey<TileDCSState> m_DCSStateKey{this, + "TileDCS", "TileDCS", "Input Tile DCS status"}; + + SG::ReadHandleKey<TileRawChannelContainer> m_rawChannelContainerKey{this, + "TileRawChannelContainer", "TileRawChannelOpt2", "Input Tile reference raw channel container key"}; + + SG::ReadHandleKey<TileRawChannelContainer> m_dspRawChannelContainerKey{this, + "TileRawChannelContainerDSP", "TileRawChannelCnt", "Input Tile DSP raw channel container key"}; + + /** + * @brief Name of TileBadChannels in condition store + */ + SG::ReadCondHandleKey<TileBadChannels> m_badChannelsKey{this, + "TileBadChannels", "TileBadChannels", "Input Tile bad channel status"}; + + /** + * @brief Name of TileEMScale in condition store + */ + SG::ReadCondHandleKey<TileEMScale> m_emScaleKey{this, + "TileEMScale", "TileEMScale", "Input Tile EMS calibration constants"}; + + /** + * @brief Name of Tile cabling service + */ + ServiceHandle<TileCablingSvc> m_cablingSvc{ this, + "TileCablingSvc", "TileCablingSvc", "The Tile cabling service"}; + + /** + * @brief Name of ROB data provider service + */ + ServiceHandle<IROBDataProviderSvc> m_robSvc{this, + "ROBDataProviderSvc", "ROBDataProviderSvc", "The ROB data provider service"}; + + const TileHWID* m_tileHWID{nullptr}; + const TileCablingService* m_cabling{nullptr}; + TileRawChannelUnit::UNIT m_finalRawChannelUnit{TileRawChannelUnit::Invalid}; + + std::vector<int> m_rodFragSizeMapGroups; + std::vector<int> m_rodFragSizeLBGroups; + std::vector<std::vector<std::vector<int>>> m_rodFragSizeGroups; + + std::vector<std::vector<int>> m_energyDiffGroups; + std::vector<std::vector<int>> m_energyDiffVsTimeGroups; + std::vector<std::vector<int>> m_energyDiffVsEnergyGroups; + std::vector<std::vector<int>> m_timeDiffGroups; + std::vector<std::vector<int>> m_timeDiffVsTimeGroups; + std::vector<std::vector<int>> m_timeDiffVsEnergyGroups; + std::vector<std::vector<int>> m_dspChanTimeGroups; + + std::vector<uint32_t> m_tileRobIds; + static const int MAX_TILE_ROBS = 32; +}; + + +#endif // TILEMONITORING_TILERODMONITORALGORITHM_H diff --git a/TileCalorimeter/TileMonitoring/src/components/TileMonitoring_entries.cxx b/TileCalorimeter/TileMonitoring/src/components/TileMonitoring_entries.cxx index 2570ba2eb2a66e7dc62709d3b07802f8592bec5f..e5df98c9de6cd240502cf4cd2ba9419ca48bf056 100644 --- a/TileCalorimeter/TileMonitoring/src/components/TileMonitoring_entries.cxx +++ b/TileCalorimeter/TileMonitoring/src/components/TileMonitoring_entries.cxx @@ -35,6 +35,7 @@ #include "../TileRawChannelTimeMonitorAlgorithm.h" #include "../TileRawChannelNoiseMonitorAlgorithm.h" #include "../TileMuonFitMonitorAlgorithm.h" +#include "../TileRODMonitorAlgorithm.h" DECLARE_COMPONENT( TileFatherMonTool ) DECLARE_COMPONENT( TilePaterMonTool ) @@ -73,3 +74,4 @@ DECLARE_COMPONENT( TileDigiNoiseMonitorAlgorithm ) DECLARE_COMPONENT( TileRawChannelTimeMonitorAlgorithm ) DECLARE_COMPONENT( TileRawChannelNoiseMonitorAlgorithm ) DECLARE_COMPONENT( TileMuonFitMonitorAlgorithm ) +DECLARE_COMPONENT( TileRODMonitorAlgorithm )