diff --git a/TileCalorimeter/TileSimAlgs/src/TilePulseForTileMuonReceiver.cxx b/TileCalorimeter/TileSimAlgs/src/TilePulseForTileMuonReceiver.cxx index 0c1ff8f57b6d1b44c1a6cedf473889198d117a83..78ebac94f0f85bc8dba0a12c237e74b7145d9347 100644 --- a/TileCalorimeter/TileSimAlgs/src/TilePulseForTileMuonReceiver.cxx +++ b/TileCalorimeter/TileSimAlgs/src/TilePulseForTileMuonReceiver.cxx @@ -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 */ //*************************************************************************************** @@ -22,6 +22,7 @@ // 10.dec.2013 ready for submission in svn // 16.jan.2014 fixed coverity errors // 06.oct.2015 including the barrel cells +// 21.jun.2020 MC pileup overlay // // BUGS: // @@ -56,6 +57,11 @@ #include <CLHEP/Random/Randomize.h> #include <CLHEP/Units/SystemOfUnits.h> + +// pileup +#include "PileUpTools/PileUpMergeSvc.h" + + using CLHEP::RandGaussQ; using CLHEP::RandFlat; using CLHEP::MeV; @@ -78,9 +84,9 @@ TilePulseForTileMuonReceiver::TilePulseForTileMuonReceiver(std::string name, ISv , m_nBinsPerX(0) , m_binTime0(0) , m_timeStep(0.0) - , m_run2(true) + , m_mergeSvc(nullptr) + , m_runPeriod(0) { - } // destructor @@ -96,10 +102,9 @@ StatusCode TilePulseForTileMuonReceiver::initialize() { // ATH_CHECK( m_cablingSvc.retrieve() ); m_cablingService = m_cablingSvc->cablingService(); - - if (! m_cablingService->isRun2Cabling() ) { + m_runPeriod = m_cablingService->runPeriod(); + if ( m_runPeriod == 0) { ATH_MSG_INFO("TilePulseForTileMuonReceiver should not be used for RUN1 simulations"); - m_run2 = false; return StatusCode::SUCCESS; } else { ATH_MSG_INFO("Initializing TilePulseForTileMuonReceiver"); @@ -163,9 +168,28 @@ StatusCode TilePulseForTileMuonReceiver::initialize() { m_tileBadChanTool.disable(); } - ATH_CHECK( m_hitContainerKey.initialize(m_run2) ); - ATH_CHECK( m_muRcvDigitsContainerKey.initialize(m_run2) ); - ATH_CHECK( m_muRcvRawChannelContainerKey.initialize(m_run2) ); + ATH_MSG_INFO( "Integer digits: \t" << ((m_integerDigits)?"true":"false")); + ATH_MSG_INFO( "Tile Pedestal: \t" << ((m_tilePedestal)?"true":"false")); + ATH_MSG_INFO( "Tile Noise: \t" << ((m_tileNoise)?"true":"false")); + ATH_MSG_INFO( "Event Overlay: \t" << ((m_rndmEvtOverlay)?"true":"false")); + ATH_MSG_INFO( "Masking Channels: \t" << ((m_maskBadChannels)?"true":"false")); + ATH_MSG_INFO( "Pulse shapes from COOL: \t" << ((m_useCoolPulseShapes)?"true":"false")); + + ATH_CHECK( m_hitContainerKey.initialize(true) ); + ATH_CHECK( m_muRcvDigitsContainerKey.initialize(true) ); + ATH_CHECK( m_muRcvRawChannelContainerKey.initialize(true) ); + + m_inputDigitContainerName = m_inputDigitContainerKey.key(); + ATH_CHECK( m_inputDigitContainerKey.initialize(!m_onlyUseContainerName && m_rndmEvtOverlay) ); + + if (m_rndmEvtOverlay) { + ATH_MSG_INFO( "Pileup and/or noise added by overlaying digits of random events"); + // locate the PileUpMergeSvc and initialize our local ptr + if (m_onlyUseContainerName) { + ATH_CHECK( service("PileUpMergeSvc", m_mergeSvc) ); + ATH_MSG_INFO( "PileUpMergeSvc successfully initialized"); + } + } ATH_MSG_VERBOSE("TilePulseForTileMuonReceiver initialization completed"); return StatusCode::SUCCESS; @@ -173,18 +197,16 @@ StatusCode TilePulseForTileMuonReceiver::initialize() { // execute // - StatusCode TilePulseForTileMuonReceiver::execute() { - if (m_run2) { - ATH_MSG_VERBOSE( "ATT: RUN2 settings TilePulseForTileMuonReceiver will run now" ); - ATH_MSG_DEBUG( "Executing TilePulseForTileMuonReceiver" ); - } else { + if (m_runPeriod==0) { ATH_MSG_VERBOSE( "ATT: RUN1 settings TilePulseForTileMuonReceiver will end now" ); return StatusCode::SUCCESS; + } else { + ATH_MSG_DEBUG( "Executing TilePulseForTileMuonReceiver" ); } - // Conversion from TMDB channel number to channel number in a drawer: EB (0-3) LB(0-13) + // Conversion from TMDB channel number to channel number in a drawer: EB (0-3) LB (0-8) // Including the cells used in the "The potential of using the ATLAS Tile calorimeter in Phase-II for the // Level-0 muon trigger" (ATL-COM-TILECAL-2015-007.pdf): ALL D-layer + BC-8. // @@ -197,8 +219,10 @@ StatusCode TilePulseForTileMuonReceiver::execute() { // Set to maximum possible index #if (nEBchan > nLBchan) double pDigitSamplesArray[nEBchan][7]; + double pDigitSamplesRndmArray[nEBchan][7]; #else double pDigitSamplesArray[nLBchan][7]; + double pDigitSamplesRndmArray[nLBchan][7]; #endif // PULSE @@ -222,7 +246,6 @@ StatusCode TilePulseForTileMuonReceiver::execute() { double muRcv_Ped; double muRcv_Calib; double muRcv_Max; - // double muRcv_Thresh; // Get hit container from TES // @@ -249,12 +272,69 @@ StatusCode TilePulseForTileMuonReceiver::execute() { SG::VIEW_ELEMENTS); ATH_CHECK( muRcvRawChannelContainer->status() ); + // Prepare container for MC Overlay procedure + // + TileDigitsContainer::const_iterator collItrRndm; + TileDigitsContainer::const_iterator lastCollRndm; + std::unique_ptr<TileMutableDigitsContainer> backgroundDigitContainer{}; + + if (m_rndmEvtOverlay) { + + ATH_MSG_DEBUG("Prepare background container for MC Overlay procedure"); + + backgroundDigitContainer = std::make_unique<TileMutableDigitsContainer>(true, + TileFragHash::Digitizer, + TileRawChannelUnit::ADCcounts); + ATH_CHECK( backgroundDigitContainer->status() ); + + if (m_onlyUseContainerName) { + typedef PileUpMergeSvc::TimedList<TileDigitsContainer>::type TimedDigitContList; + TimedDigitContList digitContList; + ATH_CHECK( m_mergeSvc->retrieveSubEvtsData(m_inputDigitContainerName, digitContList)); + ATH_MSG_DEBUG( "TileDigitsCnt successfully retrieved "); + + if (digitContList.size() == 0) { + ATH_MSG_WARNING( "No overlay done ... "); + return StatusCode::SUCCESS; + } + + TimedDigitContList::iterator iTzeroDigitCont(digitContList.begin()); + for (const auto* digitCollection : *(iTzeroDigitCont->second)) { + for (const auto* digit : *digitCollection) { + auto pDigits = std::make_unique<TileDigits>(*digit); + ATH_CHECK(backgroundDigitContainer->push_back(std::move(pDigits))); + } + } + } else { + SG::ReadHandle<TileDigitsContainer> tileDigitsContainerHandle(m_inputDigitContainerKey); + if (tileDigitsContainerHandle.isValid()) { + for (const auto* digitCollection : *tileDigitsContainerHandle) { + for (const auto* digit : *digitCollection) { + auto pDigits = std::make_unique<TileDigits>(*digit); + ATH_CHECK(backgroundDigitContainer->push_back(std::move(pDigits))); + } + } + } else { + ATH_MSG_ERROR("ReadHandle to Background Digits is invalid."); + return StatusCode::FAILURE; + } + } + + collItrRndm = backgroundDigitContainer->begin(); + lastCollRndm = backgroundDigitContainer->end(); + } // Vector of digits to set into the container // std::vector<float> digitsBuffer(m_nSamples); + // Vector(s) for MC Overlay procedure + // + std::vector<float> digitsBuffer_rndm(m_nSamples); + std::vector<bool> good_bkg( 9 , false ); + // Prepare RNG service + // ATHRNG::RNGWrapper* rngWrapper = m_rndmSvc->getEngine(this, m_randomStreamName); rngWrapper->setSeed( m_randomStreamName, Gaudi::Hive::currentContext() ); @@ -290,10 +370,69 @@ StatusCode TilePulseForTileMuonReceiver::execute() { // m_tileHWID->get_hash(drawer_id, idhash, &drawer_context); + // ************************************************************** + // + // Prepare buffer for MC Overlay procedure: pileup digits + // + + memset(pDigitSamplesRndmArray, 0, sizeof(pDigitSamplesRndmArray)); + + if (m_rndmEvtOverlay && collItrRndm != lastCollRndm) { + + const TileDigitsCollection *bkgDigitCollection(*collItrRndm); + + if (hitCollection->identify() != bkgDigitCollection->identify()) { + ATH_MSG_ERROR ( "Frag IDs for hit collection and digits overlay collection do not match " + << MSG::hex << hitCollection->identify() << " != " << bkgDigitCollection->identify() + << MSG::dec ); + return StatusCode::FAILURE; + } + + ATH_MSG_DEBUG("Prepare buffer (digitsBuffer_rndm) for MC Overlay procdure: pileup digits"); + + for (const auto* bkgDigit : *bkgDigitCollection) { + bool good_channel = true; + /* Get digit HWIdentifier (= adc_id) */ + HWIdentifier adc_id_rndm = (*bkgDigit).adc_HWID(); + int channel = m_tileHWID->channel(adc_id_rndm); + ATH_MSG_VERBOSE ( "check channels from adc id in rndm container (TMDB channel): "<< channel ); + /* Get digits */ + digitsBuffer_rndm = (*bkgDigit).samples(); + /* Get number of sample and compare with nSamples */ + int nsamp_rndm = digitsBuffer_rndm.size(); + if (nsamp_rndm != m_nSamples) { + digitsBuffer_rndm.resize(m_nSamples); + if (nsamp_rndm>0) { + for (int js=nsamp_rndm; js<m_nSamples; ++js) { + digitsBuffer_rndm[js] = digitsBuffer_rndm[js-1]; + } + } + } + /* Fill the background digits array for the current channel and set a flag if any digit is NULL */ + for (int j=0; j< m_nSamples;j++) { + pDigitSamplesRndmArray[channel][j] = digitsBuffer_rndm[j]; + // If any digit is 0 something should be wrong so flag it in order to use during overlay the standard + // path to fill the expected background level for that channel + if (pDigitSamplesRndmArray[channel][j]==0) good_channel = false; + } + good_bkg[channel] = good_channel; + + if (msgLvl(MSG::VERBOSE)){ + msg(MSG::VERBOSE) << " Digits from pileup background " << channel << " " << ros << " " << drawer << " " << m_tileHWID->to_string(adc_id_rndm)<<" | "; + for (int j=0; j< (int) digitsBuffer_rndm.size(); j++) msg(MSG::VERBOSE) << digitsBuffer_rndm[j] <<" | "; + msg(MSG::VERBOSE) << "---> | "; + for (int j=0; j< (int) digitsBuffer_rndm.size(); j++) msg(MSG::VERBOSE) << pDigitSamplesRndmArray[channel][j] << " | "; + msg(MSG::VERBOSE) << endmsg; + } + } + ++collItrRndm; // skip to next digi collection + } + ////////////////////////////////////////////////////////////////////////////// // (a.1) Iterate over all hits in a collection : access 'channel' // - if ( hitCollection->empty() ) ATH_MSG_DEBUG("-- No hits in this drawer! Filling channels with noise and pedestal. --"); + + if ( hitCollection->empty() ) ATH_MSG_DEBUG("-- No hits in this drawer! Filling channels with either noise and pedestal or MC pileup overlay. --"); for (const TileHit* tile_hit : *hitCollection) { @@ -305,10 +444,9 @@ StatusCode TilePulseForTileMuonReceiver::execute() { // int tower = m_tileID->tower(pmt_id); int sample = m_tileID->sample(pmt_id); - if ( ! ((sample == TileID::SAMP_D) || (sample == TileID::SAMP_BC && tower == 7)) ) - continue; + if ( ! ((sample == TileID::SAMP_D) || (sample == TileID::SAMP_BC && tower == 7)) ) continue; - ATH_MSG_VERBOSE("(B.00) ++ Iterate over all the D layer channels with hits for TMDB"); + ATH_MSG_VERBOSE("(B.00) ++ Iterate over all the D layer channels with hits"); // In COOL database data will be organized acoording to TMDB channel (TMDBchan): 0..n with n=5 in EB and n=8 in LB int TMDBchan; @@ -316,35 +454,37 @@ StatusCode TilePulseForTileMuonReceiver::execute() { int TILEchan; if (eb_ros) { - // cells D5, D6 and then D4 at the end - if (m_tileID->side(pmt_id) > 0) - TMDBchan = 1 - m_tileID->pmt(pmt_id) + ((tower>9) ? (tower - 10) : 4); - else - TMDBchan = m_tileID->pmt(pmt_id) + ((tower>9) ? (tower - 10) : 4); - TILEchan=EBchan[TMDBchan]; + // cells D5, D6 and then D4 at the end + if (m_tileID->side(pmt_id) > 0) + TMDBchan = 1 - m_tileID->pmt(pmt_id) + ((tower>9) ? (tower - 10) : 4); + else + TMDBchan = m_tileID->pmt(pmt_id) + ((tower>9) ? (tower - 10) : 4); + + TILEchan=EBchan[TMDBchan]; } else { // Barrel (extension for HL-LHC) if (tower == 0) { - TMDBchan = 0; // cell D0, channel 0 always + TMDBchan = 0; // cell D0, channel 0 always } else { // cells D1. D2, D3 and BC8 if (m_tileID->side(pmt_id) > 0) - TMDBchan = 1 - m_tileID->pmt(pmt_id) + ((tower<7) ? (tower-1) : 7); + TMDBchan = 1 - m_tileID->pmt(pmt_id) + ((tower<7) ? (tower-1) : 7); else - TMDBchan = m_tileID->pmt(pmt_id) + ((tower<7) ? (tower-1) : 7); + TMDBchan = m_tileID->pmt(pmt_id) + ((tower<7) ? (tower-1) : 7); } + TILEchan=LBchan[TMDBchan]; } double* pDigitSamples = pDigitSamplesArray[TMDBchan]; if (msgLvl(MSG::VERBOSE)){ - HWIdentifier adc_id = m_tileHWID->adc_id(drawer_id, TMDBchan, TileID::LOWGAIN); + HWIdentifier adc_id = m_tileHWID->adc_id(drawer_id, TMDBchan, TileID::LOWGAIN); - ATH_MSG_VERBOSE( "(B.01) Correct pmt being transported in XXchan[]: "<<TMDBchan<<" "<<TILEchan<< "=?" + ATH_MSG_VERBOSE( "(B.01) Correct pmt being transported in XXchan[]: "<<TMDBchan<<" "<<TILEchan<< "=?" << m_tileHWID->channel(m_cablingService->s2h_channel_id(pmt_id)) << " For reference get TMDB adc_id: " << m_tileHWID->to_string(adc_id) ); - ATH_MSG_VERBOSE( "(B.02) New hit in ROS/DRAWER/PMT "<<ros<<"/"<<drawer<<"/"<<TMDBchan<<" ("<<TILEchan<<")" + ATH_MSG_VERBOSE( "(B.02) New hit in ROS/DRAWER/PMT "<<ros<<"/"<<drawer<<"/"<<TMDBchan<<" ("<<TILEchan<<")" << " pmt_id "<< m_tileID->to_string(pmt_id,-1) << " adc_id "<< m_tileHWID->to_string(adc_id) ); } @@ -366,16 +506,13 @@ StatusCode TilePulseForTileMuonReceiver::execute() { for (int ihit = 0; ihit < n_hits; ++ihit) { - ATH_MSG_VERBOSE("(C.00) ++ Iterating over the hits of channel " << TILEchan <<": hit #" << ihit); + ATH_MSG_VERBOSE("(C.00) ++ Iterating over the hits of channel " << TILEchan <<": hit " << ihit <<"/"<< n_hits); double e_hit = tile_hit->energy(ihit); // [MeV] energy deposited in scintillator - double e_pmt = e_hit * hit_calib; // [MeV] true cell energy + double e_pmt = e_hit * hit_calib; // [MeV] true cell energy ATH_MSG_VERBOSE("(C.01) Energy in scintillator [MeV]: " << e_hit << " true cell energy [MeV]: " << e_pmt); - // Need to pass the negative of t_hit, this is because the trigger returns the amplitude - // at a given phase whereas the t_hit returns it from t=0 when the hit took place - // double t_hit = tile_hit->time(ihit); ATH_MSG_VERBOSE("(C.02.01) Phase " << t_hit); @@ -432,68 +569,67 @@ StatusCode TilePulseForTileMuonReceiver::execute() { } // END if (m_useCoolPulseShapes) } // END loop over sub-HITS - ATH_MSG_VERBOSE("(C.04) ENDED Loop over hits"); - ATH_MSG_DEBUG(" Number of hits " << n_hits - << " channel " << m_tileHWID->to_string(drawer_id,-2) << "/" << TMDBchan << "<-->" << TILEchan - << " digitized pulse [MeV] "<< pDigitSamples[0] + ATH_MSG_VERBOSE("++ ENDED Loop over hits for a channel"); + ATH_MSG_DEBUG("(C.04) Went over " << n_hits << " hits for channel" + << m_tileHWID->to_string(drawer_id,-2) << "/" << TMDBchan << " (" << TILEchan << ")" + << " digits [MeV] "<< pDigitSamples[0] << "/" << pDigitSamples[1] << "/" << pDigitSamples[2] << "/" << pDigitSamples[3] << "/" << pDigitSamples[4] << "/" << pDigitSamples[5] << "/" << pDigitSamples[6]); - + ATH_MSG_VERBOSE("++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"); } // END loop over a HIT collection - ///////////////////////////////////////////////////////////////////////// - // (a.3) The pulse has a shape and a amplitude in MeV now it is converted - // into ADC counts and add the NOISE and the PEDESTAL + ATH_MSG_VERBOSE("++ END loop over a HIT collection"); + + /////////////////////////////////////////////////////////////////////////////////// + // (a.3) The pulse has a shape and a amplitude in MeV now it is converted into ADC + // counts and either add NOISE and PEDESTAL or the OVERLAY digits + // // PEDESTAL [ADC counts] and NOISE [ADC counts] as stored in Tile - // Conditions (for NOW are fixed values LATER from COOL) + // Conditions (FIXED values but also flag for collection from COOL) + // // Keep containers for each module (each partition) the same size - // between events + // between events i.e. ALL channels are filled even with ZERO energy // + + ATH_MSG_VERBOSE("++ START filling of channels with background either noise+pedestal or overlay"); + for (int TMDBchan = 0; TMDBchan < upperLim; ++TMDBchan) { double* pDigitSamples=pDigitSamplesArray[TMDBchan]; int TILEchan = (eb_ros) ? EBchan[TMDBchan] : LBchan[TMDBchan]; HWIdentifier adc_id = m_tileHWID->adc_id(drawer_id, TMDBchan, TileID::LOWGAIN); - - ATH_MSG_DEBUG( "(D.00) ++ Add noise and pedestal in " + + ATH_MSG_DEBUG( "(D.) Going now to channel " << " TMDBchan: " << TMDBchan << " TILEchan: " << TILEchan); + ATH_MSG_DEBUG( "(D.00) Add noise and pedestal in " << " TMDBchan: " << TMDBchan << " TILEchan: " << TILEchan << " ROS: " << ros << " drawer: " << drawer << " drawer idx: " << drawerIdx << " drawer_id: " << m_tileHWID->to_string(drawer_id,-2) << " channel: " << m_tileHWID->to_string(adc_id,-1)); - - // Different for each channel_id might be the case in the future (now a const. in TileInfoLoader.cxx) - // - muRcv_NoiseSigma = m_tileInfo->MuRcvNoiseSigma(adc_id); // [adc] - // muRcv_Thresh = m_tileInfo->MuRcvThresh(adc_id); // [adc] ... not used - muRcv_Ped = m_tileInfo->MuRcvPed(adc_id); // [adc] - muRcv_Calib = m_tileInfo->MuRcvCalib(adc_id); // pCb->[adc] - muRcv_Max = m_tileInfo->MuRcvMax(adc_id); // [adc] - - ATH_MSG_VERBOSE( "(D.01) Tile Muon Receiver parameters:" - << " sig " << muRcv_NoiseSigma - << " noi " << muRcv_NoiseSigma - << " ped " << muRcv_Ped - << " cal " << muRcv_Calib - << " max " << muRcv_Max); - // adc/pCb / MeV/pCb = adc/MeV // + muRcv_Max = m_tileInfo->MuRcvMax(adc_id); // [adc] + muRcv_Calib = m_tileInfo->MuRcvCalib(adc_id); // pCb->[adc] double mev2ADC_factor = muRcv_Calib / m_tileToolEmscale->channelCalib(drawerIdx,TILEchan,TileID::LOWGAIN, 1. - , TileRawChannelUnit::PicoCoulombs - , TileRawChannelUnit::MegaElectronVolts); - - // Generate an array to randomize the noise for each digit - // - RandGaussQ::shootArray(*rngWrapper, m_nSamples, Rndm, 0.0, 1.0); - - ATH_MSG_VERBOSE( "(D.02) Pulse digits [MeV]:" + , TileRawChannelUnit::PicoCoulombs + , TileRawChannelUnit::MegaElectronVolts); + ATH_MSG_VERBOSE( "(D.01) Channel: "<<ros<<'/'<<drawer<<'/'<< TMDBchan + << " adc/pCb: "<< muRcv_Calib + << " Mev/pCb: "<< m_tileToolEmscale->channelCalib( drawerIdx, + TILEchan, + TileID::LOWGAIN, + 1., + TileRawChannelUnit::PicoCoulombs, + TileRawChannelUnit::MegaElectronVolts) + << " final calibration factor adc/MeV: "<< mev2ADC_factor); + + ATH_MSG_VERBOSE( "(D.02) Pulse digits [MeV]:" << " " << pDigitSamples[0] << " " << pDigitSamples[1] << " " << pDigitSamples[2] @@ -503,107 +639,151 @@ StatusCode TilePulseForTileMuonReceiver::execute() { << " " << pDigitSamples[6] << " [All ZERO if there is no hit in channel.] "); - ATH_MSG_VERBOSE( "(D.02.00) Channel: "<<ros<<'/'<<drawer<<'/'<< TMDBchan - << " adc/pCb: "<< muRcv_Calib - << " Mev/pCb: "<< m_tileToolEmscale->channelCalib( drawerIdx, - TILEchan, - TileID::LOWGAIN, - 1., - TileRawChannelUnit::PicoCoulombs, - TileRawChannelUnit::MegaElectronVolts) - << " final calibration factor adc/MeV: "<< mev2ADC_factor); - - // Collecting pedestal from the database - // - if (m_tilePedestal) { - pedSim = m_tileToolNoiseSample->getPed(idhash, TMDBchan, TileID::LOWGAIN); - // As in TileDigitsMaker bug fix for wrong ped value in DB - // - if (pedSim == 0.0) pedSim = 30.; + if ( good_bkg[TMDBchan] ) { + // Collecting digits for MC Overlay procedure from overlay container + // IF good digits ere collected (no ZEROS <> good_bkg[TMDBchan]==true) then add the background to the simulated digits + // ELSE bad digits (any ZEROS <> good_bkg[TMDBchan]==false) then follow the standard path adding muRcv_Ped and muRvc_NoiseSigma + + ATH_MSG_DEBUG("++ Adding to signal digits -- The MC PILE-UP OVERLAY digits " << m_rndmEvtOverlay << " " << m_integerDigits); + + for (int js = 0; js < m_nSamples; ++js) { + // Signal + // + ATH_MSG_VERBOSE( "(D.02.0"<< js+1 <<") sample "<< js+1 <<" E_{Signal} [adc]: "<< pDigitSamples[js] * mev2ADC_factor <<" -- Overlay"); + digitsBuffer[js] = pDigitSamples[js] * mev2ADC_factor; + // Pileup + // + ATH_MSG_VERBOSE( "(D.02.0"<< js+1 <<") sample "<< js+1 <<" E_{PileUp} [adc]: "<< pDigitSamplesRndmArray[TMDBchan][js] <<" -- Overlay"); + digitsBuffer[js] += pDigitSamplesRndmArray[TMDBchan][js]; + // Simulated pulse above allowed maximum + // + if (digitsBuffer[js] > muRcv_Max) digitsBuffer[js] = muRcv_Max; + // Rounding the ADC counts + // + if (m_integerDigits) digitsBuffer[js] = round(digitsBuffer[js]); + ATH_MSG_VERBOSE( "(D.02.0"<< js+1 <<") sample "<< js+1 <<" calibration [adc/MeV] "<< mev2ADC_factor <<"-> E_{Signal+PileUp} [adc]: "<< digitsBuffer[js] <<" -- Overlay"); + } } else { - pedSim = muRcv_Ped; - } - // Collecting noise from the database - // - if (m_tileNoise) { - RandFlat::shootArray(*rngWrapper, 1, Rndm_dG, 0.0, 1.0); - sigma_Hfn1 = m_tileToolNoiseSample->getHfn1(idhash, TMDBchan, TileID::LOWGAIN); - sigma_Hfn2 = m_tileToolNoiseSample->getHfn2(idhash, TMDBchan, TileID::LOWGAIN); - if (sigma_Hfn1 > 0 || sigma_Hfn2) { - sigma_Norm = sigma_Hfn1 / (sigma_Hfn1 + sigma_Hfn2 * m_tileToolNoiseSample->getHfnNorm(idhash, TMDBchan, TileID::LOWGAIN)); + if (m_rndmEvtOverlay) ATH_MSG_INFO("At least one digit is zero in background file using the stadart path to fill pedestal and noise in digits"); + // Different for each channel_id might be the case in the future (now a const. in TileInfoLoader.cxx) + // + muRcv_NoiseSigma = m_tileInfo->MuRcvNoiseSigma(adc_id); // [adc] + muRcv_Ped = m_tileInfo->MuRcvPed(adc_id); // [adc] + + ATH_MSG_VERBOSE( "(D.03) Tile Muon Receiver parameters:" + << " noi " << muRcv_NoiseSigma + << " ped " << muRcv_Ped + << " cal " << muRcv_Calib + << " max " << muRcv_Max); + + // Collecting digits for standard procedure NO OVERLAY: pedestal+noise + // ADD digitsBuffer[m_nSamples] WITH Ped and Noise from COOLDB/ATHENA + // + ATH_MSG_DEBUG("++ Adding to signal digits -- The PEDESTAL + NOISE digits "<< m_tilePedestal <<" "<< m_tileNoise << " " << m_integerDigits); + // Collecting pedestal from the database + // + if (m_tilePedestal) { + pedSim = m_tileToolNoiseSample->getPed(idhash, TMDBchan, TileID::LOWGAIN); + // As in TileDigitsMaker bug fix for wrong ped value in DB + // + if (pedSim == 0.0) pedSim = 30.; } else { - sigma_Hfn1 = m_tileToolNoiseSample->getHfn(idhash, TMDBchan, TileID::LOWGAIN); - sigma_Norm = 1.; + pedSim = muRcv_Ped; } - if (Rndm_dG[0] < sigma_Norm) sigmaSim = sigma_Hfn1; - else sigmaSim = sigma_Hfn2; - } else { - sigmaSim = muRcv_NoiseSigma; - } - // Loop over samples and either use noise and ped from db or user location (TileInfoLoader.cxx) - // - for (int js = 0; js < m_nSamples; ++js) { - ATH_MSG_VERBOSE( "(D.02.0"<< js <<") sample "<< js <<" E [MeV]: "<< pDigitSamples[js]); - digitsBuffer[js] = pDigitSamples[js] * mev2ADC_factor; - ATH_MSG_VERBOSE( "(D.02.0"<< js <<") sample "<< js <<" calibration Mev->adc "<< mev2ADC_factor <<"-> E [adc]: "<< digitsBuffer[js]); - // Pedestal (amp) - // - digitsBuffer[js] += pedSim; - ATH_MSG_VERBOSE( "(D.02.0"<< js <<") sample "<< js <<" adding pedestal "<< pedSim <<"-> E [adc]: "<< digitsBuffer[js]); - // Noise (rms) - // - digitsBuffer[js] += sigmaSim * Rndm[js]; - ATH_MSG_VERBOSE( "(D.02.0"<< js <<") sample "<< js <<" adding noise "<< sigmaSim * Rndm[js] <<"-> E [adc]: "<< digitsBuffer[js]); - // Simulated pulse above allowed maximum + // Collecting noise from the database // - if (digitsBuffer[js] > muRcv_Max) digitsBuffer[js] = muRcv_Max; - // Rounding the ADC counts + if (m_tileNoise) { + // Generate an array to randomize the noise for each digit + // + RandGaussQ::shootArray(*rngWrapper, m_nSamples, Rndm, 0.0, 1.0); + RandFlat::shootArray(*rngWrapper, 1, Rndm_dG, 0.0, 1.0); + sigma_Hfn1 = m_tileToolNoiseSample->getHfn1(idhash, TMDBchan, TileID::LOWGAIN); + sigma_Hfn2 = m_tileToolNoiseSample->getHfn2(idhash, TMDBchan, TileID::LOWGAIN); + if (sigma_Hfn1 > 0 || sigma_Hfn2) { + sigma_Norm = sigma_Hfn1 / (sigma_Hfn1 + sigma_Hfn2 * m_tileToolNoiseSample->getHfnNorm(idhash, TMDBchan, TileID::LOWGAIN)); + } else { + sigma_Hfn1 = m_tileToolNoiseSample->getHfn(idhash, TMDBchan, TileID::LOWGAIN); + sigma_Norm = 1.; + } + if (Rndm_dG[0] < sigma_Norm) sigmaSim = sigma_Hfn1; + else sigmaSim = sigma_Hfn2; + } else { + sigmaSim = muRcv_NoiseSigma; + } + // Loop over samples and either use noise and ped from db or user location (TileInfoLoader.cxx) // - if (m_integerDigits) digitsBuffer[js] = round(digitsBuffer[js]); + for (int js = 0; js < m_nSamples; ++js) { + // Signal + // + ATH_MSG_VERBOSE( "(D.02.0"<< js+1 <<") sample "<< js+1 <<" E [MeV]: "<< pDigitSamples[js]); + digitsBuffer[js] = pDigitSamples[js] * mev2ADC_factor; + ATH_MSG_VERBOSE( "(D.02.0"<< js+1 <<") sample "<< js+1 <<" calibration [adc/MeV] "<< mev2ADC_factor <<"-> E [adc]: "<< digitsBuffer[js]); + // Pedestal (amp) + // + digitsBuffer[js] += pedSim; + ATH_MSG_VERBOSE( "(D.02.0"<< js+1 <<") sample "<< js+1 <<" adding pedestal "<< pedSim <<"-> E [adc]: "<< digitsBuffer[js]); + // Noise (rms) + // + if (m_tileNoise) { + digitsBuffer[js] += sigmaSim * Rndm[js]; + ATH_MSG_VERBOSE( "(D.02.0"<< js+1 <<") sample "<< js+1 <<" adding noise "<< sigmaSim * Rndm[js] <<"-> E [adc]: "<< digitsBuffer[js]); + } + // Simulated pulse above allowed maximum + // + if (digitsBuffer[js] > muRcv_Max) digitsBuffer[js] = muRcv_Max; + // Rounding the ADC counts + // + if (m_integerDigits) digitsBuffer[js] = round(digitsBuffer[js]); + } } + // If channel is good, create TileDigits object and store in container. // bool chanIsBad = false; + if (m_maskBadChannels) { TileBchStatus status = m_tileBadChanTool->getAdcStatus(drawerIdx, TILEchan, TileID::LOWGAIN); chanIsBad = status.isBad(); } + if (chanIsBad) { for (int js = 0; js < m_nSamples; ++js) { - digitsBuffer[js] = 255;// in TMDB we have 8-bit ADCs + digitsBuffer[js] = 255;// in TMDB we have 8-bit ADCs } ATH_MSG_VERBOSE( "(D.03) Masking Channel: "<< ros << '/' << drawer << '/' << TILEchan <<" ("<< TMDBchan <<") LowGain" ); } else { - ATH_MSG_VERBOSE( "(D.03) Good Channel: "<< ros << '/' << drawer << '/' << TILEchan <<" ("<< TMDBchan <<") LowGain" ); + ATH_MSG_VERBOSE( "(D.03) Good Channel : "<< ros << '/' << drawer << '/' << TILEchan <<" ("<< TMDBchan <<") LowGain" ); } - ATH_MSG_VERBOSE( "(D.04) Changed to TMDB adc_id: " << m_tileHWID->to_string(adc_id) - << " and create a TileDigits object and set it into a container." ); + + ATH_MSG_VERBOSE( "++ Changed to TMDB adc_id: " << m_tileHWID->to_string(adc_id) << " and save a TileDigits object into a container." ); std::unique_ptr<TileDigits> muonReceiverDigits = std::make_unique<TileDigits>(adc_id, digitsBuffer); - ATH_MSG_VERBOSE( "(D.05) Create a TileRawChannelObject object and set it into a container " ); + ATH_MSG_VERBOSE( "++ Create a TileRawChannelObject object and set it into a container " ); TileRawChannel* muRcvRawChannel = m_MuRcvBuildTool->rawChannel(muonReceiverDigits.get()); ATH_CHECK( muRcvDigitsContainer->push_back(std::move(muonReceiverDigits)) ); ATH_CHECK( muRcvRawChannelContainer->push_back(muRcvRawChannel) ); if (msgLvl(MSG::DEBUG)){ - ATH_MSG_DEBUG( " Channel " << m_tileHWID->to_string(adc_id,-1) - << " Digitized pulse [ADC] "<< digitsBuffer[0] - << "/" << digitsBuffer[1] - << "/" << digitsBuffer[2] - << "/" << digitsBuffer[3] - << "/" << digitsBuffer[4] - << "/" << digitsBuffer[5] - << "/" << digitsBuffer[6] ); - ATH_MSG_DEBUG( " Raw channel reconstruction Ch: "<< m_tileHWID->to_string(adc_id,-1) - <<" E [ADC]: "<< muRcvRawChannel->amplitude() - <<" Time [ns]: "<< muRcvRawChannel->time() - <<" Qf: "<< muRcvRawChannel->quality() ); + ATH_MSG_DEBUG( "++ Channel " << m_tileHWID->to_string(adc_id,-1) + << " Digitized pulse [ADC] "<< digitsBuffer[0] + << "/" << digitsBuffer[1] + << "/" << digitsBuffer[2] + << "/" << digitsBuffer[3] + << "/" << digitsBuffer[4] + << "/" << digitsBuffer[5] + << "/" << digitsBuffer[6] ); + ATH_MSG_DEBUG( "++ Raw channel reconstruction Ch: "<< m_tileHWID->to_string(adc_id,-1) + <<" E [ADC]: "<< muRcvRawChannel->amplitude() + <<" Time [ns]: "<< muRcvRawChannel->time() + <<" Qf: "<< muRcvRawChannel->quality() ); } } } // END loop over all HIT collections in container if (msgLvl(MSG::VERBOSE)) muRcvDigitsContainer->print(); - // (b) Register the digits container in the TES + + ///////////////////////////////////////////////////////////////////////// + // (a.4) Register the digits container in the TES // - ATH_MSG_VERBOSE ( "(A.05) Send to event store all collected objects " ); + ATH_MSG_VERBOSE ( "(A.05) Send to event store all collected objects " ); SG::WriteHandle<TileDigitsContainer> muRcvDigitsCnt(m_muRcvDigitsContainerKey); ATH_CHECK( muRcvDigitsCnt.record(std::move(muRcvDigitsContainer)) ); diff --git a/TileCalorimeter/TileSimAlgs/src/TilePulseForTileMuonReceiver.h b/TileCalorimeter/TileSimAlgs/src/TilePulseForTileMuonReceiver.h index d46d58126d0dad749992bc8f36e49c71d9a9ff56..b7672882d6beb6b4bb86e74e361a192554938ec2 100644 --- a/TileCalorimeter/TileSimAlgs/src/TilePulseForTileMuonReceiver.h +++ b/TileCalorimeter/TileSimAlgs/src/TilePulseForTileMuonReceiver.h @@ -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 */ //**************************************************************************** @@ -24,9 +24,10 @@ // UseCoolPedestal "Pedestal from database (default=false)" // RndmSvc "Random Number Service used in TilePulseForTileMuonReceiver" // TileRawChannelBuilderMF "The tool by default is the Matched Filter" +// UseRndmEvtOverlay "Pileup and/or noise added by overlaying rando events (default=false)" // // BUGS: -// +// // History: // // @@ -55,6 +56,8 @@ #include "GaudiKernel/ToolHandle.h" #include "GaudiKernel/ServiceHandle.h" +#include "CLHEP/Random/RandomEngine.h" + class IAthRNGSvc; class PileUpMergeSvc; class HWIdentifier; @@ -83,6 +86,9 @@ class TilePulseForTileMuonReceiver: public AthAlgorithm { private: + SG::ReadHandleKey<TileDigitsContainer> m_inputDigitContainerKey{this, "InputTileDigitContainer","",""}; + std::string m_inputDigitContainerName{""}; + SG::ReadHandleKey<TileHitContainer> m_hitContainerKey{this, "TileHitContainer","TileHitCnt", "Input Tile hit container key"}; @@ -123,13 +129,15 @@ class TilePulseForTileMuonReceiver: public AthAlgorithm { Gaudi::Property<bool> m_useCoolPulseShapes{this, "UseCoolPulseShapes", false, "Pulse shapes from database (default=false)"}; Gaudi::Property<bool> m_tileNoise{this, "UseCoolNoise", false, "Noise from database (default=false)"}; Gaudi::Property<bool> m_tilePedestal{this, "UseCoolPedestal", false, "Pedestal from database (default=false)"}; + Gaudi::Property<bool> m_rndmEvtOverlay{this, "RndmEvtOverlay", false, "Pileup and/or noise added by overlaying random events (default=false)"}; + Gaudi::Property<bool> m_onlyUseContainerName{this, "OnlyUseContainerName", true, "Don't use the ReadHandleKey directly. Just extract the container name from it."}; const TileID* m_tileID; const TileHWID* m_tileHWID; const TileInfo* m_tileInfo; const TileCablingService* m_cablingService; //!< TileCabling instance - int m_nSamples; //!< Number of time slices for each channel + int m_nSamples; //!< Number of time slices for each channel int m_iTrig; //!< Index of the triggering time slice int m_adcMax; //!< ADC saturation value double m_tileThresh; //!< Actual threshold value @@ -141,12 +149,12 @@ class TilePulseForTileMuonReceiver: public AthAlgorithm { int m_binTime0; //!< Index of time=0 bin for pulse shape double m_timeStep; //!< Time step in pulse shape: 25.0 / nBinsPerX + PileUpMergeSvc* m_mergeSvc; //!< Pointer to PileUpMergeService // vector container for the pulse shape // std::vector<double> m_shapeMuonReceiver;//!< Muon receiver pulse shape - - bool m_run2; + int m_runPeriod; }; #endif diff --git a/Tools/PROCTools/python/RunTier0TestsTools.py b/Tools/PROCTools/python/RunTier0TestsTools.py index dbd129d34e99c6360267b2882bd284c43f9f8ad9..04e9076c566e00b7b07519b90a3cbae305cadeca 100644 --- a/Tools/PROCTools/python/RunTier0TestsTools.py +++ b/Tools/PROCTools/python/RunTier0TestsTools.py @@ -31,7 +31,7 @@ ciRefFileMap = { # OverlayTier0Test_required-test 'overlay-d1498-21.0' : 'v2', 'overlay-d1498-22.0' : 'v38', - 'overlay-d1592-22.0' : 'v5', + 'overlay-d1592-22.0' : 'v6', 'overlay-bkg-21.0' : 'v1', 'overlay-bkg-22.0' : 'v4', 'dataoverlay-d1590-22.0' : 'v8',