diff --git a/Configuration/StandardSequences/python/Reconstruction_cff.py b/Configuration/StandardSequences/python/Reconstruction_cff.py index 3d9341d5cf0a5..cf742103ef9e5 100644 --- a/Configuration/StandardSequences/python/Reconstruction_cff.py +++ b/Configuration/StandardSequences/python/Reconstruction_cff.py @@ -90,7 +90,7 @@ ########################################### _fastSim_localrecoTask = localrecoTask.copyAndExclude([ castorreco, - totemRPLocalReconstructionTask,totemTimingLocalReconstructionTask,ctppsDiamondLocalReconstructionTask, + totemRPLocalReconstructionTask,totemTimingLocalReconstructionTask,diamondSampicLocalReconstructionTask,ctppsDiamondLocalReconstructionTask, ctppsLocalTrackLiteProducer,ctppsPixelLocalReconstructionTask,ctppsProtons, trackerlocalrecoTask ]) diff --git a/DQM/CTPPS/plugins/DiamondSampicDQMSource.cc b/DQM/CTPPS/plugins/DiamondSampicDQMSource.cc new file mode 100644 index 0000000000000..0b4e5198029b2 --- /dev/null +++ b/DQM/CTPPS/plugins/DiamondSampicDQMSource.cc @@ -0,0 +1,761 @@ +/**************************************************************************** + * + * This is a part of CTPPSDQM software. + * Authors: + * Christopher Misan + * Nicola Minafra + * Laurent Forthomme + * + ****************************************************************************/ + +#include "FWCore/Framework/interface/ESHandle.h" +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/EventSetup.h" +#include "FWCore/Framework/interface/MakerMacros.h" +#include "FWCore/Framework/interface/Run.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/Utilities/interface/InputTag.h" + +#include "DQMServices/Core/interface/DQMOneEDAnalyzer.h" +#include "DQMServices/Core/interface/DQMStore.h" + +#include "DataFormats/CTPPSDigi/interface/TotemFEDInfo.h" +#include "DataFormats/CTPPSDigi/interface/TotemVFATStatus.h" +#include "DataFormats/CTPPSReco/interface/TotemRPLocalTrack.h" +#include "DataFormats/Common/interface/DetSetVector.h" +#include "DataFormats/FEDRawData/interface/FEDNumbering.h" +#include "DataFormats/Provenance/interface/EventRange.h" + +#include "DataFormats/CTPPSDetId/interface/CTPPSDiamondDetId.h" +#include "DataFormats/CTPPSDigi/interface/TotemTimingDigi.h" +#include "DataFormats/CTPPSReco/interface/TotemTimingRecHit.h" + +#include "DataFormats/CTPPSDetId/interface/TotemRPDetId.h" +#include "DataFormats/CTPPSReco/interface/TotemTimingLocalTrack.h" +#include "Geometry/Records/interface/VeryForwardRealGeometryRecord.h" +#include "Geometry/VeryForwardGeometryBuilder/interface/CTPPSGeometry.h" + +#include + +//---------------------------------------------------------------------------------------------------- + +namespace totemds { + struct Cache { + std::unordered_map> hitDistribution2dMap; + + std::unordered_map hitsCounterMap; + }; +} // namespace totemds + +class DiamondSampicDQMSource : public DQMOneEDAnalyzer> { +public: + DiamondSampicDQMSource(const edm::ParameterSet &); + ~DiamondSampicDQMSource() override; + +protected: + void dqmBeginRun(const edm::Run &, const edm::EventSetup &) override; + void bookHistograms(DQMStore::IBooker &, const edm::Run &, const edm::EventSetup &) override; + void analyze(const edm::Event &, const edm::EventSetup &) override; + std::shared_ptr globalBeginLuminosityBlock(const edm::LuminosityBlock &, + const edm::EventSetup &) const override; + void globalEndLuminosityBlock(const edm::LuminosityBlock &, const edm::EventSetup &) override; + +private: + // Constants + static const double SEC_PER_LUMI_SECTION; // Number of seconds per + // lumisection: used to compute hit + // rates in Hz + static const double LHC_CLOCK_PERIOD_NS; + static const double DQM_FRACTION_OF_EVENTS; // approximate fraction of events + // sent to DQM stream + static const double HIT_RATE_FACTOR; // factor to have real rate in Hz + static const double DISPLAY_RESOLUTION_FOR_HITS_MM; // Bin width of histograms + // showing hits and tracks + // (in mm) + static const double INV_DISPLAY_RESOLUTION_FOR_HITS_MM; + static const double SAMPIC_ADC_V; + + edm::EDGetTokenT> tokenLocalTrack_; + edm::EDGetTokenT> tokenDigi_; + edm::EDGetTokenT> tokenRecHit_; + edm::EDGetTokenT> tokenTrack_; + edm::EDGetTokenT> tokenFEDInfo_; + + edm::ESGetToken ctppsGeometryRunToken_; + + unsigned int samplesForNoise_; + unsigned int verbosity_; + bool plotOnline_; + bool perLSsaving_; //to avoid nanoDQMIO crashing, driven by DQMServices/Core/python/DQMStore_cfi.py + unsigned int trackCorrelationThreshold_; + edm::TimeValue_t timeOfPreviousEvent_; + + std::unordered_map horizontalShiftOfDiamond_; + + /// plots related to the whole system + struct GlobalPlots { + MonitorElement *digiSentPercentage = nullptr; + + GlobalPlots() {} + GlobalPlots(DQMStore::IBooker &ibooker); + }; + + GlobalPlots globalPlot_; + + struct SectorPlots { + // Tracks + MonitorElement *trackCorrelation = nullptr; + MonitorElement *trackCorrelationLowMultiplicity = nullptr; + MonitorElement *digiSentPercentage = nullptr; + SectorPlots(){}; + SectorPlots(DQMStore::IBooker &ibooker, unsigned int id, bool plotOnline); + }; + std::unordered_map sectorPlots_; + + /// plots related to one Diamond detector package + struct PotPlots { + // Digis + MonitorElement *activityPerBX = nullptr; + MonitorElement *digiDistribution = nullptr; + MonitorElement *dataSamplesRaw = nullptr; + MonitorElement *baseline = nullptr; + MonitorElement *noiseRMS = nullptr; + + MonitorElement *digiSent = nullptr; + MonitorElement *digiAll = nullptr; + MonitorElement *digiSentPercentage = nullptr; + + // RecHits + MonitorElement *hitDistribution2d = nullptr; + MonitorElement *hitDistribution2dWithTime = nullptr; + MonitorElement *hitDistribution2d_lumisection = nullptr; + + MonitorElement *recHitTime = nullptr; + MonitorElement *amplitude = nullptr; + MonitorElement *baselineRMS = nullptr; + MonitorElement *triggerCellTime = nullptr; + MonitorElement *meanAmplitude = nullptr; + MonitorElement *cellOfMax = nullptr; + + MonitorElement *hitRate = nullptr; + + MonitorElement *planesWithDigis = nullptr; + MonitorElement *planesWithTime = nullptr; + + MonitorElement *trackDistribution = nullptr; + + std::set planesWithDigisSet; + std::set planesWithTimeSet; + + PotPlots(){}; + PotPlots(DQMStore::IBooker &ibooker, unsigned int id, bool plotOnline); + }; + + std::unordered_map potPlots_; + + /// plots related to one Diamond plane + struct PlanePlots { + MonitorElement *digiDistribution = nullptr; + + MonitorElement *hitProfile = nullptr; + MonitorElement *hitMultiplicity = nullptr; + MonitorElement *hitMultiplicityWithTime = nullptr; + + PlanePlots() {} + PlanePlots(DQMStore::IBooker &ibooker, unsigned int id); + }; + + std::unordered_map planePlots_; + + /// plots related to one Diamond channel + struct ChannelPlots { + // Digis + MonitorElement *activityPerBX = nullptr; + MonitorElement *dataSamplesRaw = nullptr; + MonitorElement *cellOfMax = nullptr; + MonitorElement *maxTimeAfterTrigger = nullptr; + + // RecHits + MonitorElement *triggerCellTime = nullptr; + MonitorElement *recHitTime = nullptr; + MonitorElement *amplitude = nullptr; + MonitorElement *noiseSamples = nullptr; + + //MonitorElement *hitTime = nullptr; + MonitorElement *hitRate = nullptr; + + ChannelPlots() {} + ChannelPlots(DQMStore::IBooker &ibooker, unsigned int id); + }; + + std::unordered_map channelPlots_; + static std::string changePathToSampic(std::string path); +}; +//---------------------------------------------------------------------------------------------------- +std::string DiamondSampicDQMSource::changePathToSampic(std::string path) { + std::string toReplace = "TimingDiamond"; + path = path.substr(path.find(toReplace) + toReplace.length()); + path = "CTPPS/DiamondSampic/" + path; + return path; +} +//---------------------------------------------------------------------------------------------------- + +// Values for all constants +const double DiamondSampicDQMSource::SEC_PER_LUMI_SECTION = 23.31; +const double DiamondSampicDQMSource::LHC_CLOCK_PERIOD_NS = 24.95; +const double DiamondSampicDQMSource::DQM_FRACTION_OF_EVENTS = 1.; +const double DiamondSampicDQMSource::HIT_RATE_FACTOR = DQM_FRACTION_OF_EVENTS / SEC_PER_LUMI_SECTION; +const double DiamondSampicDQMSource::DISPLAY_RESOLUTION_FOR_HITS_MM = 0.05; +const double DiamondSampicDQMSource::INV_DISPLAY_RESOLUTION_FOR_HITS_MM = 1. / DISPLAY_RESOLUTION_FOR_HITS_MM; +const double DiamondSampicDQMSource::SAMPIC_ADC_V = 1. / 256; +//---------------------------------------------------------------------------------------------------- + +DiamondSampicDQMSource::GlobalPlots::GlobalPlots(DQMStore::IBooker &ibooker) { + ibooker.setCurrentFolder("CTPPS/DiamondSampic"); + digiSentPercentage = ibooker.book2D( + "sent digis percentage", "sent digis percentage (sampic);board + 0.5 sampic;channel", 14, -0.5, 6.5, 16, 0, 16); +} + +//---------------------------------------------------------------------------------------------------- + +DiamondSampicDQMSource::SectorPlots::SectorPlots(DQMStore::IBooker &ibooker, unsigned int id, bool plotOnline) { + std::string path, title; + CTPPSDiamondDetId(id).armName(path, CTPPSDiamondDetId::nPath); + ibooker.setCurrentFolder(DiamondSampicDQMSource::changePathToSampic(path)); + + CTPPSDiamondDetId(id).armName(title, CTPPSDiamondDetId::nFull); + + trackCorrelation = ibooker.book2D("tracks correlation near-far", + title + " tracks correlation near-far;x (mm);x (mm)", + 19. * INV_DISPLAY_RESOLUTION_FOR_HITS_MM, + -1, + 18, + 19. * INV_DISPLAY_RESOLUTION_FOR_HITS_MM, + -1, + 18); + trackCorrelationLowMultiplicity = + ibooker.book2D("tracks correlation with low multiplicity near-far", + title + " tracks correlation with low multiplicity near-far;x (mm);x (mm)", + 19. * INV_DISPLAY_RESOLUTION_FOR_HITS_MM, + -1, + 18, + 19. * INV_DISPLAY_RESOLUTION_FOR_HITS_MM, + -1, + 18); + if (plotOnline) + digiSentPercentage = ibooker.book2D("sent digis percentage", + title + " sent digis percentage (sampic);board + 0.5 sampic;channel", + 14, + -0.5, + 6.5, + 16, + 0, + 16); +} + +//---------------------------------------------------------------------------------------------------- + +DiamondSampicDQMSource::PotPlots::PotPlots(DQMStore::IBooker &ibooker, unsigned int id, bool plotOnline) { + std::string path, title; + CTPPSDiamondDetId(id).rpName(path, CTPPSDiamondDetId::nPath); + ibooker.setCurrentFolder(DiamondSampicDQMSource::changePathToSampic(path)); + + CTPPSDiamondDetId(id).rpName(title, CTPPSDiamondDetId::nFull); + + digiDistribution = + ibooker.book2D("digi distribution", title + " digi distribution;plane;channel", 10, -0.5, 4.5, 12, 0, 12); + + hitDistribution2d = ibooker.book2D("hits in planes", + title + " hits in planes;plane number;x (mm)", + 10, + -0.5, + 4.5, + 19. * INV_DISPLAY_RESOLUTION_FOR_HITS_MM, + -0.5, + 18.5); + hitDistribution2dWithTime = ibooker.book2D("hits in planes with time", + title + " hits in planes with time;plane number;x (mm)", + 10, + -0.5, + 4.5, + 19. * INV_DISPLAY_RESOLUTION_FOR_HITS_MM, + -0.5, + 18.5); + + recHitTime = ibooker.book1D("recHit time", title + " recHit time; t (ns)", 500, -25, 25); + trackDistribution = ibooker.book1D( + "tracks", title + " tracks;x (mm)", 19. * INV_DISPLAY_RESOLUTION_FOR_HITS_MM, -1, 18); //TODO needs tracks + + if (plotOnline) { + hitDistribution2d_lumisection = + ibooker.book2D("hits in planes lumisection", + title + " hits in planes in the last lumisection;plane number;x (mm)", + 18, + -0.5, + 4, + 15. * INV_DISPLAY_RESOLUTION_FOR_HITS_MM, + 0, + 15); + triggerCellTime = ibooker.book1D("trigger cell time", title + " Trigger Cell Time; t (ns)", 390, -25, 25); + activityPerBX = ibooker.book1D("activity per BX CMS", title + " Activity per BX;Event.BX", 3600, -1.5, 3598. + 0.5); + amplitude = ibooker.book1D("amplitude", title + " amplitude above baseline; amplitude (V)", 50, 0, 1); + baselineRMS = ibooker.book2D("noise RMS", title + " noise RMS (V);plane;channel", 10, -0.5, 4.5, 12, 0, 12); + meanAmplitude = + ibooker.book2D("mean amplitude", title + " Mean Amplitude (V);plane;channel", 10, -0.5, 4.5, 12, 0, 12); + cellOfMax = ibooker.book2D("cell of max", title + " cell of max (0-23);plane;channel", 10, -0.5, 4.5, 12, 0, 12); + + //hitRate = ibooker.book2D("hit rate", title + " hit rate (Hz);plane;channel", 10, -0.5, 4.5, 12, 0, 12); + + planesWithDigis = ibooker.book1D("active planes digis", + title + " active planes with digis sent (per event);number of active planes", + 6, + -0.5, + 5.5); + planesWithTime = ibooker.book1D( + "active planes with time", title + " active planes with time (per event);number of active planes", 6, -0.5, 5.5); + + dataSamplesRaw = ibooker.book1D("raw Samples", title + " Raw Samples; ADC", 256, 0, 256); + + baseline = ibooker.book2D("baseline", title + " baseline (V);plane;channel", 10, -0.5, 4.5, 12, 0, 12); + noiseRMS = ibooker.book2D("noise RMS", title + " noise RMS (V);plane;channel", 10, -0.5, 4.5, 12, 0, 12); + + digiSent = ibooker.book2D( + "digis sent", title + " digi sent (sampic);board + 0.5 sampic;channel", 14, -0.5, 6.5, 16, 0, 16); + digiAll = + ibooker.book2D("all digis", title + " all digis(sampic);board + 0.5 sampic;channel", 14, -0.5, 6.5, 16, 0, 16); + digiSentPercentage = ibooker.book2D("sent digis percentage", + title + " sent digis percentage (sampic);board + 0.5 sampic;channel", + 14, + -0.5, + 6.5, + 16, + 0, + 16); + } +} + +//---------------------------------------------------------------------------------------------------- + +DiamondSampicDQMSource::PlanePlots::PlanePlots(DQMStore::IBooker &ibooker, unsigned int id) { + std::string path, title; + CTPPSDiamondDetId(id).planeName(path, CTPPSDiamondDetId::nPath); + ibooker.setCurrentFolder(DiamondSampicDQMSource::changePathToSampic(path)); + + CTPPSDiamondDetId(id).planeName(title, CTPPSDiamondDetId::nFull); + + digiDistribution = ibooker.book1D("digi distribution", title + " digi distribution;channel", 12, 0, 12); + + hitProfile = ibooker.book1D("hit distribution with time", + title + " hit distribution (with time);x(mm)", + 30. * INV_DISPLAY_RESOLUTION_FOR_HITS_MM, + 0, + 30); + + hitMultiplicity = ibooker.book1D("channels per plane", title + " channels per plane; ch per plane", 13, -0.5, 12.5); + + hitMultiplicityWithTime = ibooker.book1D( + "channels per plane with time", title + " channels per plane with time; ch per plane", 13, -0.5, 12.5); +} + +//---------------------------------------------------------------------------------------------------- + +DiamondSampicDQMSource::ChannelPlots::ChannelPlots(DQMStore::IBooker &ibooker, unsigned int id) { + std::string path, title; + CTPPSDiamondDetId(id).channelName(path, CTPPSDiamondDetId::nPath); + ibooker.setCurrentFolder(DiamondSampicDQMSource::changePathToSampic(path)); + + CTPPSDiamondDetId(id).channelName(title, CTPPSDiamondDetId::nFull); + + activityPerBX = ibooker.book1D("activity per BX", title + " Activity per BX;Event.BX", 1000, -1.5, 998. + 0.5); + dataSamplesRaw = ibooker.book1D("raw samples", title + " Raw Samples; ADC", 256, 0, 256); + cellOfMax = ibooker.book1D("cell of max", title + " cell of max; cell", 24, 0, 24); + + triggerCellTime = ibooker.book1D("sampic trigger time", title + " Sampic Trigger Time; t (ns)", 100, -25, 25); + recHitTime = ibooker.book1D("recHit Time", title + " recHit Time; t (ns)", 500, -25, 25); + amplitude = ibooker.book1D("amplitude", title + " amplitude above baseline; amplitude (V)", 50, 0, 1); + noiseSamples = ibooker.book1D("noise samples", title + " noise samples; V", 50, 0, 1); + + //hitTime = ibooker.book1D("hit time", title + "hit time;t - t_previous (us)", 100, 0, 10000); + //hitRate = ibooker.book1D("hit rate", title + "hit rate;rate (Hz)", 100, 0, 10000); +} + +//---------------------------------------------------------------------------------------------------- + +DiamondSampicDQMSource::DiamondSampicDQMSource(const edm::ParameterSet &ps) + : tokenLocalTrack_(consumes>(ps.getParameter("tagLocalTrack"))), + tokenDigi_(consumes>(ps.getParameter("tagDigi"))), + tokenRecHit_(consumes>(ps.getParameter("tagRecHits"))), + tokenTrack_(consumes>(ps.getParameter("tagTracks"))), + tokenFEDInfo_(consumes>(ps.getParameter("tagFEDInfo"))), + ctppsGeometryRunToken_(esConsumes()), + samplesForNoise_(ps.getUntrackedParameter("samplesForNoise", 5)), + verbosity_(ps.getUntrackedParameter("verbosity", 0)), + plotOnline_(ps.getUntrackedParameter("plotOnline", true)), + perLSsaving_(ps.getUntrackedParameter("perLSsaving", false)), + trackCorrelationThreshold_(ps.getUntrackedParameter("trackCorrelationThreshold", 3)), + timeOfPreviousEvent_(0) {} + +//---------------------------------------------------------------------------------------------------- + +DiamondSampicDQMSource::~DiamondSampicDQMSource() {} + +//---------------------------------------------------------------------------------------------------- + +void DiamondSampicDQMSource::dqmBeginRun(const edm::Run &iRun, const edm::EventSetup &iSetup) { + // Get detector shifts from the geometry (if present) + const CTPPSGeometry *geom = &iSetup.getData(ctppsGeometryRunToken_); + for (auto it = geom->beginSensor(); it != geom->endSensor(); it++) { + if (!CTPPSDiamondDetId::check(it->first)) + continue; + const CTPPSDiamondDetId detid(it->first); + + const DetGeomDesc *det = geom->sensorNoThrow(detid); + if (det) + horizontalShiftOfDiamond_[detid.rpId()] = det->translation().x() - det->getDiamondDimensions().xHalfWidth; + else + edm::LogProblem("DiamondSampicCalibrationDQMSource") << "ERROR: no descriptor for detId"; + } + //horizontalShiftOfDiamond_=0;//unlock the shift +} + +//---------------------------------------------------------------------------------------------------- + +void DiamondSampicDQMSource::bookHistograms(DQMStore::IBooker &ibooker, + const edm::Run &, + const edm::EventSetup &iSetup) { + ibooker.cd(); + ibooker.setCurrentFolder("CTPPS/DiamondSampic"); + + const CTPPSGeometry *geom = &iSetup.getData(ctppsGeometryRunToken_); + for (auto it = geom->beginSensor(); it != geom->endSensor(); ++it) { + if (!CTPPSDiamondDetId::check(it->first)) + continue; + const CTPPSDiamondDetId detid(it->first); + + sectorPlots_[detid.armId()] = SectorPlots(ibooker, detid.armId(), plotOnline_); + + const CTPPSDiamondDetId rpId(detid.arm(), detid.station(), detid.rp()); + potPlots_[rpId] = PotPlots(ibooker, rpId, plotOnline_); + + if (plotOnline_) { + globalPlot_ = GlobalPlots(ibooker); + const CTPPSDiamondDetId plId(detid.arm(), detid.station(), detid.rp(), detid.plane()); + planePlots_[plId] = PlanePlots(ibooker, plId); + + const CTPPSDiamondDetId chId(detid.arm(), detid.station(), detid.rp(), detid.plane(), detid.channel()); + channelPlots_[chId] = ChannelPlots(ibooker, chId); + } + } +} + +//---------------------------------------------------------------------------------------------------- + +std::shared_ptr DiamondSampicDQMSource::globalBeginLuminosityBlock(const edm::LuminosityBlock &, + const edm::EventSetup &) const { + auto d = std::make_shared(); + d->hitDistribution2dMap.reserve(potPlots_.size()); + if (!perLSsaving_ && plotOnline_) + for (auto &plot : potPlots_) + d->hitDistribution2dMap[plot.first] = + std::unique_ptr(static_cast(plot.second.hitDistribution2d_lumisection->getTH2F()->Clone())); + return d; +} + +//---------------------------------------------------------------------------------------------------- + +void DiamondSampicDQMSource::analyze(const edm::Event &event, const edm::EventSetup &eventSetup) { + // get event data + edm::Handle> timingDigis; + event.getByToken(tokenDigi_, timingDigis); + + edm::Handle> fedInfo; + event.getByToken(tokenFEDInfo_, fedInfo); + + edm::Handle> timingRecHits; + event.getByToken(tokenRecHit_, timingRecHits); + + edm::Handle> timingLocalTracks; + event.getByToken(tokenTrack_, timingLocalTracks); + + // check validity + bool valid = true; + valid &= timingDigis.isValid(); + //valid &= fedInfo.isValid(); + + if (!valid) { + if (verbosity_) { + edm::LogProblem("DiamondSampicDQMSource") + << "ERROR in DiamondSampicDQMSource::analyze > some of the required inputs " + "are not valid. Skipping this event.\n" + << " timingDigis.isValid = " << timingDigis.isValid() << "\n" + << " fedInfo.isValid = " << fedInfo.isValid(); + } + + return; + } + + // Using TotemTimingDigi + std::set boardSet; + std::unordered_map channelsPerPlane; + std::unordered_map channelsPerPlaneWithTime; + + auto lumiCache = luminosityBlockCache(event.getLuminosityBlock().index()); + + for (const auto &digis : *timingDigis) { + const CTPPSDiamondDetId detId(digis.detId()); + CTPPSDiamondDetId detId_pot(digis.detId()); + detId_pot.setPlane(0); + detId_pot.setChannel(0); + CTPPSDiamondDetId detId_plane(digis.detId()); + detId_plane.setChannel(0); + + for (const auto &digi : digis) { + // Pot Plots + if (potPlots_.find(detId_pot) != potPlots_.end()) { + potPlots_[detId_pot].digiDistribution->Fill(detId.plane(), detId.channel()); + + if (plotOnline_) { + potPlots_[detId_pot].activityPerBX->Fill(event.bunchCrossing()); + + for (auto it = digi.samplesBegin(); it != digi.samplesEnd(); ++it) { + potPlots_[detId_pot].dataSamplesRaw->Fill(*it); + } + + float boardId = digi.eventInfo().hardwareBoardId() + 0.5 * digi.eventInfo().hardwareSampicId(); + potPlots_[detId_pot].digiSent->Fill(boardId, digi.hardwareChannelId()); + + if (boardSet.find(digi.eventInfo().hardwareId()) == boardSet.end()) { + // This guarantees that every board is counted only once + boardSet.insert(digi.eventInfo().hardwareId()); + std::bitset<16> chMap(digi.eventInfo().channelMap()); + for (int i = 0; i < 16; ++i) { + if (chMap.test(i)) { + potPlots_[detId_pot].digiAll->Fill(boardId, i); + } + } + } + + potPlots_[detId_pot].planesWithDigisSet.insert(detId.plane()); + } + } + + if (plotOnline_) { + // Plane Plots + if (planePlots_.find(detId_plane) != planePlots_.end()) { + planePlots_[detId_plane].digiDistribution->Fill(detId.channel()); + + if (channelsPerPlane.find(detId_plane) != channelsPerPlane.end()) + channelsPerPlane[detId_plane]++; + else + channelsPerPlane[detId_plane] = 0; + } + + // Channel Plots + if (channelPlots_.find(detId) != channelPlots_.end()) { + channelPlots_[detId].activityPerBX->Fill(event.bunchCrossing()); + + for (auto it = digi.samplesBegin(); it != digi.samplesEnd(); ++it) + channelPlots_[detId].dataSamplesRaw->Fill(*it); + for (unsigned short i = 0; i < samplesForNoise_; ++i) + channelPlots_[detId].noiseSamples->Fill(SAMPIC_ADC_V * digi.sampleAt(i)); + + unsigned int cellOfMax = std::max_element(digi.samplesBegin(), digi.samplesEnd()) - digi.samplesBegin(); + channelPlots_[detId].cellOfMax->Fill((int)cellOfMax); + + // if (timeOfPreviousEvent_ != 0) + // channelPlots_[detId].hitTime->Fill(1e-3 * LHC_CLOCK_PERIOD_NS * + // (event.time().value() - timeOfPreviousEvent_)); + ++(lumiCache->hitsCounterMap[detId]); + } + } + } + } + // End digis + + for (const auto &rechits : *timingRecHits) { + const CTPPSDiamondDetId detId(rechits.detId()); + CTPPSDiamondDetId detId_pot(rechits.detId()); + detId_pot.setPlane(0); + detId_pot.setChannel(0); + CTPPSDiamondDetId detId_plane(rechits.detId()); + detId_plane.setChannel(0); + + for (const auto &rechit : rechits) { + if (potPlots_.find(detId_pot) != potPlots_.end()) { + float UFSDShift = 0.0; + if (rechit.yWidth() < 3) + UFSDShift = 0.5; + + TH2F *hitHistoTmp = potPlots_[detId_pot].hitDistribution2d->getTH2F(); + TAxis *hitHistoTmpYAxis = hitHistoTmp->GetYaxis(); + int startBin = + hitHistoTmpYAxis->FindBin(rechit.x() - horizontalShiftOfDiamond_[detId_pot] - 0.5 * rechit.xWidth()); + int numOfBins = rechit.xWidth() * INV_DISPLAY_RESOLUTION_FOR_HITS_MM; + for (int i = 0; i < numOfBins; ++i) { + potPlots_[detId_pot].hitDistribution2d->Fill(detId.plane() + UFSDShift, + hitHistoTmpYAxis->GetBinCenter(startBin + i)); + if (!perLSsaving_ && plotOnline_) + potPlots_[detId_pot].hitDistribution2d_lumisection->Fill(detId.plane() + UFSDShift, + hitHistoTmpYAxis->GetBinCenter(startBin + i)); + } + + //All plots with Time + if (rechit.time() != TotemTimingRecHit::NO_T_AVAILABLE) { + for (int i = 0; i < numOfBins; ++i) + potPlots_[detId_pot].hitDistribution2dWithTime->Fill(detId.plane() + UFSDShift, + hitHistoTmpYAxis->GetBinCenter(startBin + i)); + + potPlots_[detId_pot].recHitTime->Fill(rechit.time()); + if (plotOnline_) { + potPlots_[detId_pot].amplitude->Fill(rechit.amplitude()); + potPlots_[detId_pot].planesWithTimeSet.insert(detId.plane()); + + // Plane Plots + if (planePlots_.find(detId_plane) != planePlots_.end()) { + TH1F *hitProfileHistoTmp = planePlots_[detId_plane].hitProfile->getTH1F(); + int numOfBins = rechit.yWidth() * INV_DISPLAY_RESOLUTION_FOR_HITS_MM; + int startBin = hitProfileHistoTmp->FindBin(rechit.x() - horizontalShiftOfDiamond_[detId_pot] - + 0.5 * rechit.xWidth()); + numOfBins = rechit.xWidth() * INV_DISPLAY_RESOLUTION_FOR_HITS_MM; + for (int i = 0; i < numOfBins; ++i) + hitProfileHistoTmp->Fill(hitProfileHistoTmp->GetBinCenter(startBin + i)); + + if (channelsPerPlaneWithTime.find(detId_plane) != channelsPerPlaneWithTime.end()) + channelsPerPlaneWithTime[detId_plane]++; + else + channelsPerPlaneWithTime[detId_plane] = 0; + } + + if (channelPlots_.find(detId) != channelPlots_.end()) { + potPlots_[detId_pot].triggerCellTime->Fill(rechit.sampicThresholdTime()); + channelPlots_[detId].triggerCellTime->Fill(rechit.sampicThresholdTime()); + channelPlots_[detId].recHitTime->Fill(rechit.time()); + channelPlots_[detId].amplitude->Fill(rechit.amplitude()); + } + } + } + } + } + } + // End RecHits + + // Using CTPPSDiamondLocalTrack + for (const auto &tracks : *timingLocalTracks) { + CTPPSDiamondDetId detId_pot(tracks.detId()); + detId_pot.setPlane(0); + detId_pot.setChannel(0); + const CTPPSDiamondDetId detId_near(tracks.detId()); + + for (const auto &track : tracks) { + if (!track.isValid()) + continue; + if (potPlots_.find(detId_pot) == potPlots_.end()) + continue; + + TH1F *trackHistoInTimeTmp = potPlots_[detId_pot].trackDistribution->getTH1F(); + int startBin = trackHistoInTimeTmp->FindBin(track.x0() - horizontalShiftOfDiamond_[detId_pot] - track.x0Sigma()); + int numOfBins = 2 * track.x0Sigma() * INV_DISPLAY_RESOLUTION_FOR_HITS_MM; + for (int i = 0; i < numOfBins; ++i) { + trackHistoInTimeTmp->Fill(trackHistoInTimeTmp->GetBinCenter(startBin + i)); + } + + //this plot was made with 2 stations per arm in mind + for (const auto &tracks_far : *timingLocalTracks) { + CTPPSDiamondDetId detId_far(tracks_far.detId()); + detId_far.setPlane(0); + detId_far.setChannel(0); + if (detId_near.arm() != detId_far.arm() || detId_near.station() == detId_far.station()) + continue; + for (const auto &track_far : tracks_far) { + if (!track.isValid()) + continue; + if (sectorPlots_.find(detId_far.armId()) == sectorPlots_.end()) + continue; + TH2F *trackHistoTmp = sectorPlots_[detId_far.armId()].trackCorrelation->getTH2F(); + TAxis *trackHistoTmpXAxis = trackHistoTmp->GetXaxis(); + TAxis *trackHistoTmpYAxis = trackHistoTmp->GetYaxis(); + int startBin_far = + trackHistoTmpYAxis->FindBin(track_far.x0() - horizontalShiftOfDiamond_[detId_far] - track_far.x0Sigma()); + int numOfBins_far = 2 * track_far.x0Sigma() * INV_DISPLAY_RESOLUTION_FOR_HITS_MM; + for (int i = 0; i < numOfBins; ++i) { + for (int y = 0; y < numOfBins_far; ++y) { + trackHistoTmp->Fill(trackHistoTmpXAxis->GetBinCenter(startBin + i), + trackHistoTmpYAxis->GetBinCenter(startBin_far + y)); + if (tracks.size() < 3 && tracks_far.size() < trackCorrelationThreshold_) + sectorPlots_[detId_far.armId()].trackCorrelationLowMultiplicity->Fill( + trackHistoTmpXAxis->GetBinCenter(startBin + i), trackHistoTmpYAxis->GetBinCenter(startBin_far + y)); + } + } + } + } + } + } + if (plotOnline_) { + for (auto &plt : potPlots_) { + plt.second.planesWithDigis->Fill(plt.second.planesWithDigisSet.size()); + plt.second.planesWithDigisSet.clear(); + plt.second.planesWithTime->Fill(plt.second.planesWithTimeSet.size()); + plt.second.planesWithTimeSet.clear(); + } + + for (const auto &plt : channelsPerPlane) + planePlots_[plt.first].hitMultiplicity->Fill(plt.second); + + for (const auto &plt : channelsPerPlaneWithTime) + planePlots_[plt.first].hitMultiplicityWithTime->Fill(plt.second); + } + timeOfPreviousEvent_ = event.time().value(); +} + +//---------------------------------------------------------------------------------------------------- + +void DiamondSampicDQMSource::globalEndLuminosityBlock(const edm::LuminosityBlock &iLumi, const edm::EventSetup &) { + auto lumiCache = luminosityBlockCache(iLumi.index()); + if (!perLSsaving_ && plotOnline_) { + for (auto &plot : potPlots_) + *(plot.second.hitDistribution2d_lumisection->getTH2F()) = *(lumiCache->hitDistribution2dMap[plot.first]); + globalPlot_.digiSentPercentage->Reset(); + for (auto &plot : sectorPlots_) + plot.second.digiSentPercentage->Reset(); + TH2F *hitHistoGlobalTmp = globalPlot_.digiSentPercentage->getTH2F(); + for (auto &plot : potPlots_) { + TH2F *hitHistoTmp = plot.second.digiSentPercentage->getTH2F(); + TH2F *histoSent = plot.second.digiSent->getTH2F(); + TH2F *histoAll = plot.second.digiAll->getTH2F(); + + hitHistoTmp->Divide(histoSent, histoAll); + hitHistoTmp->Scale(100); + hitHistoGlobalTmp->Add(hitHistoTmp, 1); + + plot.second.baseline->Reset(); + plot.second.noiseRMS->Reset(); + plot.second.meanAmplitude->Reset(); + plot.second.cellOfMax->Reset(); + //plot.second.hitRate->Reset(); + CTPPSDiamondDetId rpId(plot.first); + TH2F *hitHistoSectorTmp = sectorPlots_[rpId.armId()].digiSentPercentage->getTH2F(); + hitHistoSectorTmp->Add(hitHistoTmp, 1); + + for (auto &chPlot : channelPlots_) { + CTPPSDiamondDetId chId(chPlot.first); + if (chId.arm() == rpId.arm() && chId.rp() == rpId.rp()) { + plot.second.baseline->Fill(chId.plane(), chId.channel(), chPlot.second.noiseSamples->getTH1F()->GetMean()); + plot.second.noiseRMS->Fill(chId.plane(), chId.channel(), chPlot.second.noiseSamples->getTH1F()->GetRMS()); + plot.second.meanAmplitude->Fill(chId.plane(), chId.channel(), chPlot.second.amplitude->getTH1F()->GetMean()); + plot.second.cellOfMax->Fill(chId.plane(), chId.channel(), chPlot.second.cellOfMax->getTH1F()->GetMean()); + //auto hitsCounterPerLumisection = lumiCache->hitsCounterMap[chPlot.first]; + //plot.second.hitRate->Fill(chId.plane(), chId.channel(), (double)hitsCounterPerLumisection * HIT_RATE_FACTOR); + } + } + } + + // for (auto &plot : channelPlots_) { + // auto hitsCounterPerLumisection = lumiCache->hitsCounterMap[plot.first]; + // if (hitsCounterPerLumisection != 0) { + // plot.second.hitRate->Fill((double)hitsCounterPerLumisection * HIT_RATE_FACTOR); + // } + // } + } +} + +DEFINE_FWK_MODULE(DiamondSampicDQMSource); diff --git a/DQM/CTPPS/python/ctppsDQM_cff.py b/DQM/CTPPS/python/ctppsDQM_cff.py index 3221dd26f2ca1..ba65ef53dca15 100644 --- a/DQM/CTPPS/python/ctppsDQM_cff.py +++ b/DQM/CTPPS/python/ctppsDQM_cff.py @@ -7,6 +7,8 @@ from DQM.CTPPS.ctppsDiamondDQMSource_cfi import * +from DQM.CTPPS.diamondSampicDQMSource_cfi import * + from DQM.CTPPS.totemTimingDQMSource_cfi import * from DQM.CTPPS.ctppsPixelDQMSource_cfi import * @@ -23,7 +25,7 @@ _ctppsDQMOnlineSource = cms.Sequence( ctppsPixelDQMSource + ctppsDiamondDQMSource - + totemTimingDQMSource + + diamondSampicDQMSourceOnline + ctppsCommonDQMSourceOnline ) @@ -35,7 +37,7 @@ totemRPDQMSource + ctppsPixelDQMSource + ctppsDiamondDQMSource - + totemTimingDQMSource + + diamondSampicDQMSourceOnline + ctppsCommonDQMSourceOnline + elasticPlotDQMSource ) @@ -52,19 +54,32 @@ #Check if perLSsaving is enabled to mask MEs vs LS from Configuration.ProcessModifiers.dqmPerLSsaving_cff import dqmPerLSsaving dqmPerLSsaving.toModify(ctppsDiamondDQMSource, perLSsaving=True) -dqmPerLSsaving.toModify(totemTimingDQMSource, perLSsaving=True) +dqmPerLSsaving.toModify(diamondSampicDQMSourceOffline, perLSsaving=True) dqmPerLSsaving.toModify(ctppsCommonDQMSourceOffline, perLSsaving=True) _ctppsDQMOfflineSource = cms.Sequence( ctppsPixelDQMOfflineSource + ctppsDiamondDQMSource - + totemTimingDQMSource + + diamondSampicDQMSourceOffline + ctppsCommonDQMSourceOffline ) _ctppsDQMOfflineHarvest = cms.Sequence( ) +from Configuration.Eras.Modifier_ctpps_2018_cff import ctpps_2018 +ctpps_2018.toReplaceWith( + _ctppsDQMOfflineSource, + cms.Sequence( + ctppsPixelDQMOfflineSource + + ctppsDiamondDQMSource + + totemTimingDQMSource + + ctppsCommonDQMSourceOffline + ) + +) + + # the actually used sequences must be empty for pre-PPS data from Configuration.Eras.Modifier_ctpps_cff import ctpps diff --git a/DQM/CTPPS/python/diamondSampicDQMSource_cfi.py b/DQM/CTPPS/python/diamondSampicDQMSource_cfi.py new file mode 100644 index 0000000000000..e4bb2a48a6d1c --- /dev/null +++ b/DQM/CTPPS/python/diamondSampicDQMSource_cfi.py @@ -0,0 +1,28 @@ +import FWCore.ParameterSet.Config as cms + +from DQMServices.Core.DQMEDAnalyzer import DQMEDAnalyzer +diamondSampicDQMSourceOnline = DQMEDAnalyzer('DiamondSampicDQMSource', + tagDigi = cms.InputTag("totemTimingRawToDigi", "TotemTiming"), + tagFEDInfo = cms.InputTag("totemTimingRawToDigi", "TotemTiming"), + tagRecHits = cms.InputTag("totemTimingRecHits"), + tagTracks = cms.InputTag("diamondSampicLocalTracks"), + tagLocalTrack = cms.InputTag("totemRPLocalTrackFitter"), + + samplesForNoise = cms.untracked.uint32(6), + + verbosity = cms.untracked.uint32(10), + plotOnline=cms.untracked.bool(True) +) + +diamondSampicDQMSourceOffline = DQMEDAnalyzer('DiamondSampicDQMSource', + tagDigi = cms.InputTag("totemTimingRawToDigi", "TotemTiming"), + tagFEDInfo = cms.InputTag("totemTimingRawToDigi", "TotemTiming"), + tagRecHits = cms.InputTag("totemTimingRecHits"), + tagTracks = cms.InputTag("diamondSampicLocalTracks"), + tagLocalTrack = cms.InputTag("totemRPLocalTrackFitter"), + + samplesForNoise = cms.untracked.uint32(6), + + verbosity = cms.untracked.uint32(10), + plotOnline=cms.untracked.bool(False) +) diff --git a/RecoPPS/Configuration/python/RecoCTPPS_EventContent_cff.py b/RecoPPS/Configuration/python/RecoCTPPS_EventContent_cff.py index df8837853ad52..309437919c3ae 100644 --- a/RecoPPS/Configuration/python/RecoCTPPS_EventContent_cff.py +++ b/RecoPPS/Configuration/python/RecoCTPPS_EventContent_cff.py @@ -20,6 +20,9 @@ 'keep TotemVFATStatusedmDetSetVector_ctppsDiamondRawToDigi_*_*', 'keep CTPPSDiamondRecHitedmDetSetVector_ctppsDiamondRecHits_*_*', 'keep CTPPSDiamondLocalTrackedmDetSetVector_ctppsDiamondLocalTracks_*_*', + + #diamond sampic + 'keep TotemTimingLocalTrackedmDetSetVector_diamondSampicLocalTracks_*_*', # TOTEM timing 'keep TotemTimingDigiedmDetSetVector_totemTimingRawToDigi_*_*', diff --git a/RecoPPS/Configuration/python/recoCTPPS_cff.py b/RecoPPS/Configuration/python/recoCTPPS_cff.py index 2bfe9320d2f11..3dd2e61d3c0b4 100644 --- a/RecoPPS/Configuration/python/recoCTPPS_cff.py +++ b/RecoPPS/Configuration/python/recoCTPPS_cff.py @@ -15,10 +15,25 @@ recoCTPPSTask = cms.Task( totemRPLocalReconstructionTask , ctppsDiamondLocalReconstructionTask , - totemTimingLocalReconstructionTask , + diamondSampicLocalReconstructionTask , ctppsPixelLocalReconstructionTask , ctppsLocalTrackLiteProducer , ctppsProtons ) +from Configuration.Eras.Modifier_ctpps_2018_cff import ctpps_2018 +ctpps_2018.toReplaceWith( + recoCTPPSTask, + cms.Task( + totemRPLocalReconstructionTask , + ctppsDiamondLocalReconstructionTask , + totemTimingLocalReconstructionTask , + ctppsPixelLocalReconstructionTask , + ctppsLocalTrackLiteProducer , + ctppsProtons + ) + +) + + recoCTPPS = cms.Sequence(recoCTPPSTask) diff --git a/RecoPPS/Local/test/totemTiming_digiConverter_reco_cfg.py b/RecoPPS/Local/test/totemTiming_digiConverter_reco_cfg.py index 0ba58aab2e89c..f1f40e2dae2d6 100644 --- a/RecoPPS/Local/test/totemTiming_digiConverter_reco_cfg.py +++ b/RecoPPS/Local/test/totemTiming_digiConverter_reco_cfg.py @@ -15,7 +15,7 @@ process.load('Configuration.StandardSequences.FrontierConditions_GlobalTag_cff') from Configuration.AlCa.GlobalTag import GlobalTag -process.GlobalTag = GlobalTag(process.GlobalTag, 'auto:run2_data', '') +process.GlobalTag = GlobalTag(process.GlobalTag, '113X_dataRun3_Prompt_Candidate_2021_08_24_17_11_47') ################ #digi converter @@ -68,24 +68,61 @@ #load calibrations from json #process.totemTimingRecHits.timingCalibrationTag= cms.string('ppsTimingCalibrationESSource:TotemTimingCalibration') #process.ppsTimingCalibrationESSource = cms.ESSource('PPSTimingCalibrationESSource', -# calibrationFile = cms.FileInPath('RecoPPS/Local/data/timing_offsets_ufsd_2018.dec18.cal.json'),#calibration file does not yet exist in db +# calibrationFile = cms.FileInPath('RecoPPS/Local/data/1plane_2.json'),#calibration file does not yet exist in db # subDetector = cms.uint32(1), # appendToDataLabel = cms.string('TotemTimingCalibration') #) +from DQMServices.Core.DQMEDAnalyzer import DQMEDAnalyzer +process.diamondSampicDQMSource = DQMEDAnalyzer('DiamondSampicDQMSource', + tagDigi = cms.InputTag("totemTimingRawToDigi", "TotemTiming"), + tagFEDInfo = cms.InputTag("totemTimingRawToDigi", "TotemTiming"), + tagRecHits = cms.InputTag("totemTimingRecHits"), + tagTracks = cms.InputTag("diamondSampicLocalTracks"), + tagLocalTrack = cms.InputTag("totemRPLocalTrackFitter"), + + minimumStripAngleForTomography = cms.double(0), + maximumStripAngleForTomography = cms.double(1), + samplesForNoise = cms.untracked.uint32(6), + + verbosity = cms.untracked.uint32(10), + plotOnline=cms.untracked.bool(False) +) +# load DQM framework +process.load("DQM.Integration.config.environment_cfi") +process.dqmEnv.subSystemFolder = "CTPPS" +process.dqmEnv.eventInfoFolder = "EventInfo" +process.dqmSaver.path = "" +process.dqmSaver.tag = "CTPPS" process.totemTimingRecHits.mergeTimePeaks= cms.bool(False) +#process.load('CondCore.CondDB.CondDB_cfi') +#process.CondDB.connect = 'sqlite_file:ppsDiamondSampicTiming_calibration.sqlite' # SQLite input +#process.PoolDBESSource = cms.ESSource('PoolDBESSource', +# process.CondDB, +# DumpStats = cms.untracked.bool(True), +# toGet = cms.VPSet( +# cms.PSet( +# record = cms.string('PPSTimingCalibrationRcd'), +# tag = cms.string('DiamondSampicCalibration') +# ) +# ) +# ) +process.totemTimingRecHits.timingCalibrationTag= cms.string('GlobalTag:DiamondSampicCalibration') + process.out = cms.OutputModule("PoolOutputModule", fileName = cms.untracked.string('file:diamondSampicReco.root') ) process.p = cms.Path(process.totemTimingRawToDigi* - process.diamondSampicLocalReconstruction + process.diamondSampicLocalReconstruction* + process.diamondSampicDQMSource ) -process.outpath = cms.EndPath(process.out) +process.outpath = cms.EndPath(process.out* process.dqmEnv * + process.dqmSaver)