diff --git a/TileCalorimeter/TileMonitoring/CMakeLists.txt b/TileCalorimeter/TileMonitoring/CMakeLists.txt index c72c669f6dcc65cdf587933f8957695d38a9277a..15ba99f5ce25e930d223135a8fafede6479b41f6 100644 --- a/TileCalorimeter/TileMonitoring/CMakeLists.txt +++ b/TileCalorimeter/TileMonitoring/CMakeLists.txt @@ -74,3 +74,8 @@ atlas_add_test( TileDQFragMonitorAlgorithm_test SCRIPT python -m TileMonitoring.TileDQFragMonitorAlgorithm PROPERTIES TIMEOUT 300 POST_EXEC_SCRIPT nopost.sh) + +atlas_add_test( TileMBTSMonitorAlgorithm_test + SCRIPT python -m TileMonitoring.TileMBTSMonitorAlgorithm + PROPERTIES TIMEOUT 300 + POST_EXEC_SCRIPT nopost.sh) diff --git a/TileCalorimeter/TileMonitoring/python/TileMBTSMonitorAlgorithm.py b/TileCalorimeter/TileMonitoring/python/TileMBTSMonitorAlgorithm.py new file mode 100644 index 0000000000000000000000000000000000000000..8d1ae560a0ec6a4206824404c664e8edfc1027fb --- /dev/null +++ b/TileCalorimeter/TileMonitoring/python/TileMBTSMonitorAlgorithm.py @@ -0,0 +1,238 @@ +# +# Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +# + +''' +@file TileMBTSMonitorAlgorithm.py +@brief Python configuration of TileMBTSMonitorAlgorithm algorithm for the Run III +''' + + +def TileMBTSMonitoringConfig(flags, **kwargs): + + ''' Function to configure TileMBTSMonitorAlgorithm 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 LArGeoAlgsNV.LArGMConfig import LArGMCfg + result.merge(LArGMCfg(flags)) + + from TileConditions.TileCablingSvcConfig import TileCablingSvcCfg + result.merge( TileCablingSvcCfg(flags) ) + + # The following class will make a sequence, configure algorithms, and link + # them to GenericMonitoringTools + from AthenaMonitoring import AthMonitorCfgHelper + helper = AthMonitorCfgHelper(flags,'TileMonitoring') + + # Adding an TileMBTSMonitorAlgorithm algorithm to the helper + from TileMonitoring.TileMonitoringConf import TileMBTSMonitorAlgorithm + tileMBTSMonAlg = helper.addAlgorithm(TileMBTSMonitorAlgorithm, 'TileMBTSMonAlg') + + tileMBTSMonAlg.TriggerChain = '' + + for k, v in kwargs.items(): + setattr(tileMBTSMonAlg, k, v) + + if 'FillHistogramsPerMBTS' in kwargs: + fillHistogramPerMBTS = kwargs['FillHistogramsPerMBTS'] + else: + fillHistogramPerMBTS = tileMBTSMonAlg.getDefaultProperty('FillHistogramsPerMBTS') + + # 1) Configure histogram with TileMBTSMonAlg algorithm execution time + executeTimeGroup = helper.addGroup(tileMBTSMonAlg, 'TileMBTSMonExecuteTime', 'Tile/') + executeTimeGroup.defineHistogram('TIME_execute', path = 'MBTS', type='TH1F', + title = 'Time for execute TileMBTSMonAlg algorithm;time [#mus]', + xbins = 100, xmin = 0, xmax = 100000) + + + run = str(flags.Input.RunNumber[0]) + numberOfMBTS = 32 + + labelsMBTS = ['MBTSA' + ('0' if x < 10 else '') + str(x) for x in range(0, numberOfMBTS / 2)] + labelsMBTS += ['MBTSC' + ('0' if x < 10 else '') + str(x) for x in range(0, numberOfMBTS / 2)] + + + # 2) Configure MBTS occupancy histogram + occupancyGroup = helper.addGroup(tileMBTSMonAlg, 'TileOccupancyMBTS', 'Tile') + occupancyGroup.defineHistogram('EnergyCounter;Occupancy', path = 'MBTS/Cell', type='TH1F', weight = 'SummaryEnergy', + labels = labelsMBTS, title = 'Run ' + run + ': MBTS Occupancy', + xbins = numberOfMBTS, xmin = 0, xmax = numberOfMBTS) + + # 3) Configure summary energy histogram + energySummaryGroup = helper.addGroup(tileMBTSMonAlg, 'TileEnergySummaryMBTS', 'Tile') + energySummaryGroup.defineHistogram('EnergyCounter,SummaryEnergy;SummaryEnergy', path = 'MBTS/Cell', type='TProfile', + title = 'Run ' + run + ': Average MBTS Energy;;Average Energy [pC]', + labels = labelsMBTS, xbins = numberOfMBTS, xmin = 0, xmax = numberOfMBTS) + + # 4) Configure histogram with average MBTS time (energy above threshold) + timeSummaryGroup = helper.addGroup(tileMBTSMonAlg, 'TileTimeSummaryMBTS', 'Tile') + timeSummaryGroup.defineHistogram('TimeCounter,SummaryTime;SummaryTime', path = 'MBTS/Cell', type='TProfile', + title = 'Run ' + run + ': Average MBTS Time (Energy above threshold);;Average Time [ns]', + labels = labelsMBTS, xbins = numberOfMBTS, xmin = 0, xmax = numberOfMBTS) + + # 5) Configure histogram with time of MBTS on A side + timeAGroup = helper.addGroup(tileMBTSMonAlg, 'TileTimeMBTSA', 'Tile') + timeAGroup.defineHistogram('TimeA;Time_A', path = 'MBTS/Cell', type='TH1F', + title = 'Run ' + run + ': Time of MBTS on A side;Time [ns]', + xbins = 151, xmin = -75.5, xmax = 75.5) + + # 6) Configure histogram time of MBTS on C side + timeCGroup = helper.addGroup(tileMBTSMonAlg, 'TileTimeMBTSC', 'Tile') + timeCGroup.defineHistogram('TimeC;Time_C', path = 'MBTS/Cell', type='TH1F', + title = 'Run ' + run + ': Time of MBTS on C side;Time [ns]', + xbins = 151, xmin = -75.5, xmax = 75.5) + + # 7) Configure histogram with time difference between MBTS on A and C sides + timeDifferenceGroup = helper.addGroup(tileMBTSMonAlg, 'TileTimeDifferenceMBTS', 'Tile') + timeDifferenceGroup.defineHistogram('TimeDifference;TimeDiff_A-C', path = 'MBTS/Cell', type='TH1F', + title = 'Run ' + run + ': Time difference between MBTS on A and C sides;Time [ns]', + xbins = 151, xmin = -75.5, xmax = 75.5) + + # 8) Configure histogram with time difference between MBTS on A and C sides vs luminosity block + timeDifferenceLBGroup = helper.addGroup(tileMBTSMonAlg, 'TileTimeDifferenceMBTSLB', 'Tile') + timeDifferenceLBGroup.defineHistogram('lumiBlock,TimeDifference;TimeDiff_A-C_LB', path = 'MBTS/Cell', type='TH2F', + title = ('Run ' + run + ': Time difference between MBTS on A and C sides vs LumiBlock' + + ';Luminosity Block;Time difference A-side - C-side [ns]'), + xbins = 1000, xmin = -0.5, xmax = 999.5, ybins = 151, ymin = -75.5, ymax = 75.5) + + # 9) Configure histogram with coincident Hits (energy) between two MBTS counters + labelsCoincidentMBTS = labelsMBTS + labelsMBTS + coincidentHitsGroup = helper.addGroup(tileMBTSMonAlg, 'TileCoincidentHitsMBTS', 'Tile') + coincidentHitsGroup.defineHistogram('CoincidentCounter1,CoincidentCounter2;CoincidentEnergyHits', + path = 'MBTS/Cell', type='TH2F', labels = labelsCoincidentMBTS, + title = 'Run ' + run + ': Coincident Hits (energy) between two MBTS counters', + xbins = numberOfMBTS, xmin = 0, xmax = numberOfMBTS, + ybins = numberOfMBTS, ymin = 0, ymax = numberOfMBTS) + + + + # 10) Configure histogram with Tile readout errors for MBTS counters + errorLabels = ['General', 'Global CRC', 'ROD CRC', 'Frontend CRC', 'BCID', 'Header Format', + 'Header Parity', 'Sample Format', 'Sample Parity', 'Memory Parity'] + numberOfErrors = len(errorLabels) + errorLabelsMBTS = labelsMBTS + errorLabels + errorsGroup = helper.addGroup(tileMBTSMonAlg, 'TileErrorsMBTS', 'Tile') + errorsGroup.defineHistogram('ErrorCounter,Error;ReadOutErrors', + path = 'MBTS/Digit', type='TH2F', labels = errorLabelsMBTS, + title = 'Run ' + run + ': Tile Readout Errors for MBTS counters', + xbins = numberOfMBTS, xmin = 0, xmax = numberOfMBTS, + ybins = numberOfErrors, ymin = 0, ymax = numberOfErrors) + + + + if fillHistogramPerMBTS: + + # 11) Configure histogram with MBTS counter energy + energyArray = helper.addArray([numberOfMBTS], tileMBTSMonAlg, 'TileEnergyMBTS', topPath = 'Tile/MBTS') + for postfix, tool in energyArray.Tools.items(): + mbtsCounter = int( postfix.split('_')[1] ) + mbtsName = labelsMBTS[mbtsCounter] + title = 'Run ' + run + ': Energy of ' + mbtsName + ';Energy [pC]' + name = 'Energy;Energy_' + mbtsName + tool.defineHistogram(name, title = title, type = 'TH1F', path = 'Cell', + xbins = 400, xmin = -0.5, xmax = 80) + + # 12) Configure histogram with MBTS counter energy vs luminosity block + energyLBArray = helper.addArray([numberOfMBTS], tileMBTSMonAlg, 'TileEnergyLBMBTS', topPath = 'Tile/MBTS') + for postfix, tool in energyLBArray.Tools.items(): + mbtsCounter = int( postfix.split('_')[1] ) + mbtsName = labelsMBTS[mbtsCounter] + title = 'Run ' + run + ': Energy of ' + mbtsName + ' per lumiblock;Lumiblocks;Energy [pC]' + name = 'lumiBlock,Energy;EnergyLB_' + mbtsName + tool.defineHistogram(name, title = title, type = 'TProfile', path = 'Cell', + xbins = 1000, xmin = -0.5, xmax = 999.5) + + # 13) Configure histogram with MBTS counter time + timeArray = helper.addArray([numberOfMBTS], tileMBTSMonAlg, 'TileTimeMBTS', topPath = 'Tile/MBTS') + for postfix, tool in timeArray.Tools.items(): + mbtsCounter = int( postfix.split('_')[1] ) + mbtsName = labelsMBTS[mbtsCounter] + title = 'Run ' + run + ': Time of ' + mbtsName + ';Time [ns]' + name = 'Time;Time_' + mbtsName + tool.defineHistogram(name, title = title, type = 'TH1F', path = 'Cell', + xbins = 151, xmin = -75.5, xmax = 75.5) + + # 14) Configure histogram with MBTS counter pedestal + pedestalArray = helper.addArray([numberOfMBTS], tileMBTSMonAlg, 'TilePedestalMBTS', topPath = 'Tile/MBTS') + for postfix, tool in pedestalArray.Tools.items(): + mbtsCounter = int( postfix.split('_')[1] ) + mbtsName = labelsMBTS[mbtsCounter] + title = 'Run ' + run + ': Pedestal of ' + mbtsName + ';Channel pedestal in ADC counts' + name = 'Pedestal;Pedestal_' + mbtsName + tool.defineHistogram(name, title = title, type = 'TH1F', path = 'Digit', + xbins = 100, xmin = 20.5, xmax = 120.5) + + # 15) Configure histogram with high frequency noise of MBTS counter + hfnArray = helper.addArray([numberOfMBTS], tileMBTSMonAlg, 'TileHFNoiseMBTS', topPath = 'Tile/MBTS') + for postfix, tool in hfnArray.Tools.items(): + mbtsCounter = int( postfix.split('_')[1] ) + mbtsName = labelsMBTS[mbtsCounter] + title = 'Run ' + run + ': High Frequency Noise of ' + mbtsName + ';Inter-sample RMS in ADC counts' + name = 'HFN;HFN_' + mbtsName + tool.defineHistogram(name, title = title, type = 'TH1F', path = 'Digit', + xbins = 100, xmin = 0, xmax = 5) + + # 16) Configure histogram with average pulse shape of MBTS counter + averagePulseArray = helper.addArray([numberOfMBTS], tileMBTSMonAlg, 'TileAveragePulseMBTS', topPath = 'Tile/MBTS') + for postfix, tool in averagePulseArray.Tools.items(): + mbtsCounter = int( postfix.split('_')[1] ) + mbtsName = labelsMBTS[mbtsCounter] + title = 'Run ' + run + ': Average Pulse for digitized signals of ' + mbtsName + title += ';TileCal Digital Sample;Average number of ADC counts' + name = 'SampleNumbers,Samples;AveragePulse_' + mbtsName + tool.defineHistogram(name, title = title, type = 'TProfile', path = 'Digit', + xbins = 7, xmin = -0.5, xmax = 6.5) + + + + 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.ESD + ConfigFlags.Output.HISTFileName = 'TileMBTSMonitorOutput.root' + ConfigFlags.lock() + + # Initialize configuration object, add accumulator, merge, and run. + from AthenaConfiguration.MainServicesConfig import MainServicesSerialCfg + from AthenaPoolCnvSvc.PoolReadConfig import PoolReadCfg + cfg = MainServicesSerialCfg() + cfg.merge(PoolReadCfg(ConfigFlags)) + + cfg.merge( TileMBTSMonitoringConfig(ConfigFlags, TileDigitsContainer = 'TileDigitsFlt') ) + + cfg.printConfig(withDetails = True, summariseProps = True) + ConfigFlags.dump() + + cfg.store( open('TileMBTSMonitorAlgorithm.pkl','w') ) + + sc = cfg.run(maxEvents=3) + + import sys + # Success should be 0 + sys.exit(not sc.isSuccess()) diff --git a/TileCalorimeter/TileMonitoring/src/TileMBTSMonitorAlgorithm.cxx b/TileCalorimeter/TileMonitoring/src/TileMBTSMonitorAlgorithm.cxx new file mode 100644 index 0000000000000000000000000000000000000000..2099c12e685e0fdcf866ce422b988b964908719a --- /dev/null +++ b/TileCalorimeter/TileMonitoring/src/TileMBTSMonitorAlgorithm.cxx @@ -0,0 +1,337 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +#include "TileMBTSMonitorAlgorithm.h" + +#include "TileIdentifier/TileHWID.h" +#include "TileIdentifier/TileFragHash.h" + +#include "CaloIdentifier/TileTBID.h" + +#include "StoreGate/ReadHandle.h" + + +StatusCode TileMBTSMonitorAlgorithm::initialize() { + + ATH_CHECK( AthMonitorAlgorithm::initialize() ); + + ATH_MSG_INFO("in initialize()"); + + if (m_energyCut.size() != MAX_MBTS_COUNTER) { + int numberOfCounters{MAX_MBTS_COUNTER}; + ATH_MSG_ERROR("Energy cuts are not provided for all (" + << numberOfCounters << ") MBTS. Provided only " + << m_energyCut.size() << " energy cuts"); + + return StatusCode::FAILURE; + } + + ATH_CHECK( m_cablingSvc.retrieve() ); + m_cabling = m_cablingSvc->cablingService(); + + ATH_CHECK( detStore()->retrieve(m_tileTBID) ); + ATH_CHECK( detStore()->retrieve(m_tileHWID) ); + + ATH_CHECK( m_DQstatusKey.initialize() ); + ATH_CHECK( m_digitsContainerKey.initialize() ); + ATH_CHECK( m_mbtsCellContainerKey.initialize() ); + + memset(m_MBTSchannels, -1, sizeof(m_MBTSchannels)); + memset(m_MBTScounters, -1, sizeof(m_MBTScounters)); + for (unsigned int ros = 3; ros < Tile::MAX_ROS ; ++ros) { + for (unsigned int drawer = 0; drawer < Tile::MAX_DRAWER; ++drawer) { + HWIdentifier drawerHWID = m_tileHWID->drawer_id(ros, drawer); + Identifier mbtsID = m_cabling->drawer2MBTS_id(drawerHWID); + if (mbtsID.is_valid()) { + int channel = m_tileHWID->channel(m_cabling->s2h_channel_id(mbtsID)); + m_MBTSchannels[ros - 3][drawer] = channel; + + int counter = getMBTSCounter(mbtsID); + m_MBTScounters[ros - 3][drawer] = counter; + + ATH_MSG_DEBUG( "Found MBTS: drawer/channel (counter)=> " << drawer << "/" << channel << "(" << counter << ")" ); + + } + } + } + + + m_energyGroups = Monitored::buildToolMap<int>(m_tools, "TileEnergyMBTS", MAX_MBTS_COUNTER); + m_energyLBGroups = Monitored::buildToolMap<int>(m_tools, "TileEnergyLBMBTS", MAX_MBTS_COUNTER); + + m_timeGroups = Monitored::buildToolMap<int>(m_tools, "TileTimeMBTS", MAX_MBTS_COUNTER); + + m_hfnGroups = Monitored::buildToolMap<int>(m_tools, "TileHFNoiseMBTS", MAX_MBTS_COUNTER); + m_pedestalGroups = Monitored::buildToolMap<int>(m_tools, "TilePedestalMBTS", MAX_MBTS_COUNTER); + + m_pulseGroups = Monitored::buildToolMap<int>(m_tools, "TileAveragePulseMBTS", MAX_MBTS_COUNTER); + + return StatusCode::SUCCESS; +} + + +StatusCode TileMBTSMonitorAlgorithm::fillHistograms( const EventContext& ctx ) const { + + // In case you want to measure the execution time + auto timer = Monitored::Timer("TIME_execute"); + auto lumiBlock = Monitored::Scalar<int>("lumiBlock", GetEventInfo(ctx)->lumiBlock()); + + int nHitsA(0); + int nHitsC(0); + double timeA(0.0); + double timeC(0.0); + + auto monEnergy = Monitored::Scalar<float>("Energy", 0.0F); + auto monTime = Monitored::Scalar<float>("Time", 0.0F); + + std::vector<float> energyCounters; + auto monEnergyCounter = Monitored::Collection("EnergyCounter", energyCounters); + + std::vector<float> energies; + auto monSummaryEnergy = Monitored::Collection("SummaryEnergy", energies); + + std::vector<float> timeCounters; + auto monTimeCounter = Monitored::Collection("TimeCounter", timeCounters); + + std::vector<float> times; + auto monSummaryTime = Monitored::Collection("SummaryTime", times); + + std::vector<int> energyHitCounters; + + SG::ReadHandle<TileCellContainer> mbtsContainer(m_mbtsCellContainerKey, ctx); + ATH_CHECK( mbtsContainer.isValid() ); + + for (const TileCell* cell : *mbtsContainer) { + + Identifier id = cell->ID(); + + // Calculate MBTS counter from "side", "tower" and "module" + // Counter goes 0-31. + // EBA-inner:0-7,EBA-outer:8-15,EBC-inner:16-23,EBC-outer:24-31 + // tower is 1 for outer counter (lower eta) and 0 for inner counter (higher eta) + // module counts from 0-7 in increasing phi + // side is -1 for EBC 1 for EBA + + int counter = getMBTSCounter(id); + energyCounters.push_back(counter); + + double energy = cell->energy(); + monEnergy = energy; + energies.push_back(energy); + + double time = cell->time(); + monTime = time; + + float quality = cell->quality(); + + ATH_MSG_VERBOSE("Counter: " << counter + << ", energy= " << energy << " pCb" + << ", time= " << time + << ", quality= " << quality); + + + if (m_fillHistogramsPerMBTS) { + fill(m_tools[m_energyGroups[counter]], monEnergy); + fill(m_tools[m_energyLBGroups[counter]], lumiBlock, monEnergy); + } + + if (energy > m_energyCut[counter]) { + + timeCounters.push_back(counter); + times.push_back(time); + + energyHitCounters.push_back(counter); + + if (m_fillHistogramsPerMBTS) { + fill(m_tools[m_timeGroups[counter]], monTime); + } + + if (std::abs(time) > 10e-4) { + if (counter < 16) { // MBTS A side + timeA += time; + ++nHitsA; + } else { // MBTS C side + timeC += time; + ++nHitsC; + } + } + + } + } + + + fill("TileOccupancyMBTS", monEnergyCounter, monSummaryEnergy); + fill("TileEnergySummaryMBTS", monEnergyCounter, monSummaryEnergy); + + fill("TileTimeSummaryMBTS", monTimeCounter, monSummaryTime); + + if (nHitsA > 0) { + timeA /= nHitsA; + auto monTimeA = Monitored::Scalar<float>("TimeA", timeA); + fill("TileTimeMBTSA", monTimeA); + } + + if (nHitsC > 0) { + timeC /= nHitsC; + auto monTimeC = Monitored::Scalar<float>("TimeC", timeC); + fill("TileTimeMBTSC", monTimeC); + } + + if (nHitsA > 0 && nHitsC > 0) { + double timeDifference = timeA - timeC; + auto monTimeDifference = Monitored::Scalar<float>("TimeDifference", timeDifference); + fill("TileTimeDifferenceMBTS", monTimeDifference); + fill("TileTimeDifferenceMBTSLB", lumiBlock, monTimeDifference); + } + + + std::vector<int> coincidentCounters1; + auto monCoincidentCounters1 = Monitored::Collection("CoincidentCounter1", coincidentCounters1); + + std::vector<int> coincidentCounters2; + auto monCoincidentCounters2 = Monitored::Collection("CoincidentCounter2", coincidentCounters2); + + for (int counter1 : energyHitCounters) { + for (int counter2 : energyHitCounters) { + coincidentCounters1.push_back(counter1); + coincidentCounters2.push_back(counter2); + } + } + + fill("TileCoincidentHitsMBTS", monCoincidentCounters1, monCoincidentCounters2); + + std::vector<int> errors; + auto monErrors = Monitored::Collection("Error", errors); + + std::vector<int> counters; + auto monErrorCounters = Monitored::Collection("ErrorCounter", counters); + + auto monPedestal = Monitored::Scalar<float>("Pedestal", 0.0F); + auto monHFN = Monitored::Scalar<float>("HFN", 0.0F); + + // Create instance of TileDQstatus used to check for readout errors in Tile + const TileDQstatus * dqStatus = SG::makeHandle (m_DQstatusKey, ctx).get(); + + SG::ReadHandle<TileDigitsContainer> digitsContainer(m_digitsContainerKey, ctx); + ATH_CHECK( digitsContainer.isValid() ); + + for (const TileDigitsCollection* digitsCollection : *digitsContainer) { + HWIdentifier adc_id = digitsCollection->front()->adc_HWID(); + int ros = m_tileHWID->ros(adc_id); + if (ros > 2) { // Extended barrel + int drawer = m_tileHWID->drawer(adc_id); + int MBTSchannel = m_MBTSchannels[ros - 3][drawer]; + + if (MBTSchannel >= 0) { + for (const TileDigits* tile_digits: *digitsCollection) { + + adc_id = tile_digits->adc_HWID(); + int channel = m_tileHWID->channel(adc_id); + if (channel == MBTSchannel) { // MBTS channel found + int gain = m_tileHWID->adc(adc_id); + int counter = m_MBTScounters[ros - 3][drawer]; + + // Fill Readout Error histogram + const int dmu = 0; + if (!(dqStatus->isChanDQgood(ros, drawer, channel))) { + setDigiError(counters, errors, counter, GENERAL); + } + if (dqStatus->checkGlobalCRCErr(ros, drawer, gain)) { + setDigiError(counters, errors, counter, GLOBAL_CRC); + } + if (dqStatus->checkROD_CRCErr(ros, drawer, dmu, gain)) { + setDigiError(counters, errors, counter, ROD_CRC); + } + if (dqStatus->checkFE_CRCErr(ros, drawer, dmu, gain)) { + setDigiError(counters, errors, counter, FRONTEND_CRC); + } + if (dqStatus->checkBCIDErr(ros, drawer, dmu, gain)) { + setDigiError(counters, errors, counter, BCID); + } + if (dqStatus->checkHeaderFormatErr(ros, drawer, dmu, gain)) { + setDigiError(counters, errors, counter, HEADER_FORMAT); + } + if (dqStatus->checkHeaderParityErr(ros, drawer, dmu, gain)) { + setDigiError(counters, errors, counter, HEADER_PARITY); + } + if (dqStatus->checkSampleFormatErr(ros, drawer, dmu, gain)) { + setDigiError(counters, errors, counter, SAMPLE_FORMAT); + } + if (dqStatus->checkSampleParityErr(ros, drawer, dmu, gain)) { + setDigiError(counters, errors, counter, SAMPLE_PARITY); + } + if (dqStatus->checkMemoryParityErr(ros, drawer, dmu, gain)) { + setDigiError(counters, errors, counter, MEMORY_PARITY); + } + + + if (m_fillHistogramsPerMBTS) { + + double sampleMean = 0; + double sampleRMS = 0; + + std::vector<float> samples = tile_digits->samples(); + unsigned int nSamples = samples.size(); + if (nSamples > 0) { + + for (float sample : samples) { + sampleMean += sample; + sampleRMS += sample * sample; + } + + auto min_max = std::minmax_element(samples.begin(), samples.end()); + float minSample = *min_max.first; + float maxSample = *min_max.second; + + if ((maxSample - minSample) > 10) { + + auto monSamples = Monitored::Collection("Samples", samples); + + std::vector<int> sampleNumbers; + for (unsigned int i = 0; i < nSamples; ++i) sampleNumbers.push_back(i); + auto monSampleNumbers = Monitored::Collection("SampleNumbers", sampleNumbers); + + fill(m_tools[m_pulseGroups[counter]], monSampleNumbers, monSamples); + } + + sampleMean /= nSamples; + sampleRMS = sampleRMS / nSamples - sampleMean * sampleMean; + sampleRMS = (sampleRMS > 0.0 && nSamples > 1u) ? sqrt(sampleRMS * nSamples / (nSamples - 1u)) : 0.0; + + monHFN = sampleRMS; + fill(m_tools[m_hfnGroups[counter]], monHFN); + + monPedestal = samples.front(); + fill(m_tools[m_pedestalGroups[counter]], monPedestal); + + } + } + } + } + } + } + } + + fill("TileErrorsMBTS", monErrorCounters, monErrors); + + fill("TileMBTSMonExecuteTime", timer); + + return StatusCode::SUCCESS; +} + + + +int TileMBTSMonitorAlgorithm::getMBTSCounter(Identifier mbtsID) const { + int counter = m_tileTBID->phi(mbtsID) + 8 * m_tileTBID->eta(mbtsID); + if (m_tileTBID->side(mbtsID) < 0) counter += 16;// EBC side + return counter; +} + + +void TileMBTSMonitorAlgorithm::setDigiError(std::vector<int>& counters, std::vector<int>& errors, + int counter, int error) const { + + counters.push_back(counter); + errors.push_back(error); +} diff --git a/TileCalorimeter/TileMonitoring/src/TileMBTSMonitorAlgorithm.h b/TileCalorimeter/TileMonitoring/src/TileMBTSMonitorAlgorithm.h new file mode 100644 index 0000000000000000000000000000000000000000..d97ae4ab22aee904486a25c06ed5ef9424b022b5 --- /dev/null +++ b/TileCalorimeter/TileMonitoring/src/TileMBTSMonitorAlgorithm.h @@ -0,0 +1,102 @@ +/* + Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef TILEMONITORING_TILEMBTSMONITORALGORITHM_H +#define TILEMONITORING_TILEMBTSMONITORALGORITHM_H + +#include "TileEvent/TileContainer.h" +#include "TileEvent/TileDigitsContainer.h" +#include "TileEvent/TileDQstatus.h" +#include "TileConditions/TileCablingSvc.h" +#include "TileCalibBlobObjs/TileCalibUtils.h" + +#include "AthenaMonitoring/AthMonitorAlgorithm.h" +#include "AthenaMonitoring/Monitored.h" + +#include "StoreGate/ReadHandleKey.h" +#include "GaudiKernel/ServiceHandle.h" + + +class TileTBID; +class TileHWID; +class TileCablingService; + +/** @class TileMBTSMonitorAlgorithm + * @brief Class for Tile MBTS based monitoring + */ + +class TileMBTSMonitorAlgorithm : public AthMonitorAlgorithm { + + public: + + using AthMonitorAlgorithm::AthMonitorAlgorithm; + + virtual ~TileMBTSMonitorAlgorithm() = default; + virtual StatusCode initialize() override; + virtual StatusCode fillHistograms( const EventContext& ctx ) const override; + + private: + + using Tile = TileCalibUtils; + + enum TileDigiErrors {GENERAL, GLOBAL_CRC, ROD_CRC, FRONTEND_CRC, BCID, HEADER_FORMAT, + HEADER_PARITY, SAMPLE_FORMAT, SAMPLE_PARITY, MEMORY_PARITY}; + + void setDigiError(std::vector<int>& counters, std::vector<int>& errors, int counter, int error) const; + + int getMBTSCounter(Identifier mbtsID) const; + + Gaudi::Property<bool> m_fillHistogramsPerMBTS{this, + "FillHistogramsPerMBTS", true, "Switch for using per MBTS histograms"}; + + Gaudi::Property<std::vector<float>> m_energyCut{this, + "EnergyCuts", + {//MBTSA00 MBTSA01 MBTSA02 MBTSA03 MBTSA04 MBTSA05 MBTSA06 MBTSA07 + 60. /222, 60. /222, 60. /222, 60. /222, 60. /222, 60. /222, 60. /222, 60. /222, + //MBTSA08 MBTSA09 MBTSA10 MBTSA11 MBTSA12 MBTSA13 MBTSA14 MBTSA15 + 60. /222, 60. /222, 60. /222, 60. /222, 60. /222, 60. /222, 60. /222, 60. /222, + //MBTSC00 MBTSC01 MBTSC02 MBTSC03 MBTSC04 MBTSC05 MBTSC06 MBTSC07 + 60. /222, 60. /222, 60. /222, 60. /222, 60. /222, 60. /222, 60. /222, 60. /222, + //MBTSC08 MBTSC09 MBTSC10 MBTSC11 MBTSC12 MBTSC13 MBTSC14 MBTSC15 + 60. /222, 60. /222, 60. /222, 60. /222, 60. /222, 60. /222, 60. /222, 60. /222}, + "Energy cuts for 32 MBTS counters (MBTSA00, .., MBTSC15)"}; + + SG::ReadHandleKey<TileDQstatus> m_DQstatusKey{this, + "TileDQstatus", "TileDQstatus", "Tile DQ status"}; + + SG::ReadHandleKey<TileDigitsContainer> m_digitsContainerKey{ this, + "TileDigitsContainer", "TileDigitsCnt", "Tile digits container" }; + + SG::ReadHandleKey<TileCellContainer> m_mbtsCellContainerKey{this, + "MBTSContainer", "MBTSContainer", "Tile MBTS container" }; + + /** + * @brief Name of Tile cabling service + */ + ServiceHandle<TileCablingSvc> m_cablingSvc{this, + "TileCablingSvc", "TileCablingSvc", "The Tile cabling service" }; + + const TileCablingService* m_cabling{nullptr}; + + std::vector<int> m_energyGroups; + std::vector<int> m_energyLBGroups; + + std::vector<int> m_timeGroups; + + std::vector<int> m_hfnGroups; + std::vector<int> m_pedestalGroups; + + std::vector<int> m_pulseGroups; + + + const TileTBID* m_tileTBID{nullptr}; + const TileHWID* m_tileHWID{nullptr}; + + int m_MBTSchannels[Tile::MAX_ROS - 3][Tile::MAX_DRAWER]; + int m_MBTScounters[Tile::MAX_ROS - 3][Tile::MAX_DRAWER]; + + static const unsigned int MAX_MBTS_COUNTER{32}; +}; + +#endif // TILEMONITORING_TILEMBTSMONITORALGORITHM_H diff --git a/TileCalorimeter/TileMonitoring/src/components/TileMonitoring_entries.cxx b/TileCalorimeter/TileMonitoring/src/components/TileMonitoring_entries.cxx index 54ca7e4e40da38755b974abafe7c124205593f81..0feaf7f983a4995d1e8495db780b82f2cca1614c 100644 --- a/TileCalorimeter/TileMonitoring/src/components/TileMonitoring_entries.cxx +++ b/TileCalorimeter/TileMonitoring/src/components/TileMonitoring_entries.cxx @@ -24,6 +24,7 @@ #include "TileMonitoring/TileTBCellMonTool.h" #include "../TileJetMonitorAlgorithm.h" #include "../TileDQFragMonitorAlgorithm.h" +#include "../TileMBTSMonitorAlgorithm.h" DECLARE_COMPONENT( TileFatherMonTool ) DECLARE_COMPONENT( TilePaterMonTool ) @@ -51,4 +52,5 @@ DECLARE_COMPONENT( TileTBMonTool ) DECLARE_COMPONENT( TileTBCellMonTool ) DECLARE_COMPONENT( TileJetMonitorAlgorithm ) DECLARE_COMPONENT( TileDQFragMonitorAlgorithm ) +DECLARE_COMPONENT( TileMBTSMonitorAlgorithm )