diff --git a/CalibPPS/TimingCalibration/plugins/BuildFile.xml b/CalibPPS/TimingCalibration/plugins/BuildFile.xml index b67b7d23683d5..83f19f4dc0ff3 100644 --- a/CalibPPS/TimingCalibration/plugins/BuildFile.xml +++ b/CalibPPS/TimingCalibration/plugins/BuildFile.xml @@ -6,4 +6,5 @@ + diff --git a/CalibPPS/TimingCalibration/plugins/PPSDiamondSampicTimingCalibrationPCLHarvester.cc b/CalibPPS/TimingCalibration/plugins/PPSDiamondSampicTimingCalibrationPCLHarvester.cc new file mode 100644 index 0000000000000..ed66659cc760a --- /dev/null +++ b/CalibPPS/TimingCalibration/plugins/PPSDiamondSampicTimingCalibrationPCLHarvester.cc @@ -0,0 +1,290 @@ +// -*- C++ -*- +// +// Package: CalibPPS/TimingCalibration/PPSDiamondSampicTimingCalibrationPCLHarvester +// Class: PPSDiamondSampicTimingCalibrationPCLHarvester +// +/**\class PPSDiamondSampicTimingCalibrationPCLHarvester PPSDiamondSampicTimingCalibrationPCLHarvester.cc CalibPPS/TimingCalibration/PPSDiamondSampicTimingCalibrationPCLHarvester/plugins/PPSDiamondSampicTimingCalibrationPCLHarvester.cc + + Description: Harvester of the DiamondSampic calibration which produces sqlite file with a new channel alignment + + Implementation: + [Notes on implementation] +*/ +// +// Original Author: Christopher Misan +// Created: Mon, 26 Jul 2021 16:36:13 GMT +// +// +#include "TAxis.h" +#include "TH1.h" +#include "TArrayD.h" +#include "DQMServices/Core/interface/DQMEDHarvester.h" + +#include "FWCore/Framework/interface/Frameworkfwd.h" +#include "FWCore/Framework/interface/MakerMacros.h" +#include "FWCore/Framework/interface/ESHandle.h" +#include "FWCore/Framework/interface/EventSetup.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/ServiceRegistry/interface/Service.h" + +#include +#include + +#include "Geometry/VeryForwardGeometryBuilder/interface/CTPPSGeometry.h" +#include "Geometry/Records/interface/VeryForwardRealGeometryRecord.h" + +#include "CalibPPS/TimingCalibration/interface/TimingCalibrationStruct.h" +#include "CondCore/DBOutputService/interface/PoolDBOutputService.h" + +#include "DataFormats/CTPPSDetId/interface/CTPPSDiamondDetId.h" +#include "CondFormats/PPSObjects/interface/PPSTimingCalibration.h" +#include "CondFormats/DataRecord/interface/PPSTimingCalibrationRcd.h" + +namespace pt = boost::property_tree; + +class PPSDiamondSampicTimingCalibrationPCLHarvester : public DQMEDHarvester { +public: + PPSDiamondSampicTimingCalibrationPCLHarvester(const edm::ParameterSet&); + void beginRun(const edm::Run&, const edm::EventSetup&) override; + static void fillDescriptions(edm::ConfigurationDescriptions&); + +private: + void dqmEndJob(DQMStore::IBooker&, DQMStore::IGetter&) override; + void calibJson(DQMStore::IGetter& iGetter); + void calibDb(DQMStore::IGetter& iGetter); + bool getDbSampicChannel( + DQMStore::IGetter& iGetter, int& db, int& sampic, int& channel, std::string ch_name, CTPPSDiamondDetId detid); + edm::ESGetToken geomEsToken_; + edm::ESGetToken timingCalibrationToken_; + edm::ESHandle hTimingCalib_; + std::vector detids_; + const std::string dqmDir_; + const unsigned int min_entries_; + const std::string jsonCalibFile_, jsonOutputPath_; +}; + +//------------------------------------------------------------------------------ + +PPSDiamondSampicTimingCalibrationPCLHarvester::PPSDiamondSampicTimingCalibrationPCLHarvester( + const edm::ParameterSet& iConfig) + : geomEsToken_(esConsumes()), + dqmDir_(iConfig.getParameter("dqmDir")), + min_entries_(iConfig.getParameter("minEntries")), + jsonCalibFile_(iConfig.getParameter("jsonCalibFile")), + jsonOutputPath_(iConfig.getParameter("jsonOutputPath")) { + if (jsonCalibFile_.empty()) + timingCalibrationToken_ = esConsumes( + edm::ESInputTag(iConfig.getParameter("timingCalibrationTag"))); +} + +//------------------------------------------------------------------------------ + +void PPSDiamondSampicTimingCalibrationPCLHarvester::beginRun(const edm::Run& iRun, const edm::EventSetup& iSetup) { + if (jsonCalibFile_.empty()) + hTimingCalib_ = iSetup.getHandle(timingCalibrationToken_); + const auto& geom = iSetup.getData(geomEsToken_); + for (auto it = geom.beginSensor(); it != geom.endSensor(); ++it) { + if (!CTPPSDiamondDetId::check(it->first)) + continue; + const CTPPSDiamondDetId detid(it->first); + detids_.emplace_back(detid); + } +} + +//------------------------------------------------------------------------------ + +bool PPSDiamondSampicTimingCalibrationPCLHarvester::getDbSampicChannel( + DQMStore::IGetter& iGetter, int& db, int& sampic, int& channel, std::string path, CTPPSDiamondDetId detid) { + auto histDb = iGetter.get(path + "db"); + auto histSampic = iGetter.get(path + "sampic"); + auto histChannel = iGetter.get(path + "channel"); + + if (histDb == nullptr) { + edm::LogWarning("PPSDiamondSampicTimingCalibrationPCLHarvester:dqmEndJob") + << "Failed to retrieve db for detid: " << detid; + return false; + } + + if (histSampic == nullptr) { + edm::LogWarning("PPSDiamondSampicTimingCalibrationPCLHarvester:dqmEndJob") + << "Failed to retrieve sampic for detid: " << detid; + return false; + } + + if (histChannel == nullptr) { + edm::LogWarning("PPSDiamondSampicTimingCalibrationPCLHarvester:dqmEndJob") + << "Failed to retrieve channel hwId for detid: " << detid; + return false; + } + + db = histDb->getIntValue(); + sampic = histSampic->getIntValue(); + channel = histChannel->getIntValue(); + + return true; +} +//------------------------------------------------------------------------------ + +void PPSDiamondSampicTimingCalibrationPCLHarvester::calibJson(DQMStore::IGetter& iGetter) { + std::unordered_map timeHisto; + std::string ch_name, path; + + pt::ptree node; + pt::read_json(jsonCalibFile_, node); + const std::string formula = node.get("formula"); + + for (const auto& detid : detids_) { + detid.channelName(path, CTPPSDiamondDetId::nPath); + detid.channelName(ch_name); + path = dqmDir_ + "/" + path + "/" + ch_name; + const auto chid = detid.rawId(); + + int db, sampic, channel; + if (!getDbSampicChannel(iGetter, db, sampic, channel, path, detid)) + continue; + + int ct = 0; + for (pt::ptree::value_type& par : node.get_child("parameters." + std::to_string(db))) { + double new_time_offset; + if (ct == 16 * (1 - sampic) + channel) { //flip the calibration - sampic 1 is first in json + double old_time_offset = par.second.get("time_offset"); + + timeHisto[chid] = iGetter.get(path); + + if (timeHisto[chid] == nullptr) { + edm::LogWarning("PPSDiamondSampicTimingCalibrationPCLHarvester:dqmEndJob") + << "Failed to retrieve time monitor for detid" << detid; + par.second.put("time_offset", old_time_offset); + continue; + } + + if (min_entries_ > 0 && timeHisto[chid]->getEntries() < min_entries_) { + edm::LogWarning("PPSDiamondSampicTimingCalibrationPCLHarvester:dqmEndJob") + << "Not enough entries for channel (" << detid << "): " << timeHisto[chid]->getEntries() << " < " + << min_entries_ << ". Skipping calibration."; + par.second.put("time_offset", old_time_offset); + continue; + } + new_time_offset = old_time_offset - timeHisto[chid]->getMean(); + //scale x axis of the plots by calculated offset + timeHisto[chid]->getTH1F()->GetXaxis()->Set( + timeHisto[chid]->getTH1F()->GetXaxis()->GetNbins(), + timeHisto[chid]->getTH1F()->GetXaxis()->GetXmin() + new_time_offset, // new Xmin + timeHisto[chid]->getTH1F()->GetXaxis()->GetXmax() + new_time_offset); // new Xmax + timeHisto[chid]->getTH1F()->ResetStats(); + + par.second.put("time_offset", new_time_offset); + break; + } + ct++; + } + } + pt::write_json(jsonOutputPath_, node); +} + +//------------------------------------------------------------------------------ + +void PPSDiamondSampicTimingCalibrationPCLHarvester::calibDb(DQMStore::IGetter& iGetter) { + PPSTimingCalibration calib = *hTimingCalib_; + + // book the parameters containers + PPSTimingCalibration::ParametersMap params; + PPSTimingCalibration::TimingMap time_info; + + std::unordered_map timeHisto; + std::string rp_name, plane_name, ch_name, path; + const std::string& formula = calib.formula(); + + for (const auto& detid : detids_) { + detid.channelName(path, CTPPSDiamondDetId::nPath); + detid.channelName(ch_name); + path = dqmDir_ + "/" + path + "/" + ch_name; + const auto chid = detid.rawId(); + + int db, sampic, channel; + if (!getDbSampicChannel(iGetter, db, sampic, channel, path, detid)) + continue; + + PPSTimingCalibration::Key key; + key.db = db; + key.sampic = sampic; + key.channel = channel; + + double timeOffset = calib.timeOffset(db, sampic, channel); + double timePrecision = calib.timePrecision(db, sampic, channel); + if (timeOffset == 0 && timePrecision == 0) { + edm::LogWarning("PPSDiamondSampicTimingCalibrationPCLHarvester:dqmEndJob") + << "No calibration found for db: " << db << " sampic: " << sampic << " channel: " << channel; + continue; + } + + int cell_ct = 0; + while (!calib.parameters(db, sampic, channel, cell_ct).empty()) { + auto parameters = calib.parameters(db, sampic, channel, cell_ct); + key.cell = cell_ct; + params[key] = parameters; + cell_ct++; + } + + key.cell = -1; + + time_info[key] = {timeOffset, timePrecision}; + timeHisto[chid] = iGetter.get(path); + if (timeHisto[chid] == nullptr) { + edm::LogWarning("PPSDiamondSampicTimingCalibrationPCLHarvester:dqmEndJob") + << "Failed to retrieve time monitor for detid: " << detid; + continue; + } + + if (min_entries_ > 0 && timeHisto[chid]->getEntries() < min_entries_) { + edm::LogInfo("PPSDiamondSampicTimingCalibrationPCLHarvester:dqmEndJob") + << "Not enough entries (" << detid << "): " << timeHisto[chid]->getEntries() << " < " << min_entries_ + << ". Skipping calibration."; + continue; + } + + double new_time_offset = timeOffset - timeHisto[chid]->getMean(); + //scale x axis of the plots by calculated offset + timeHisto[chid]->getTH1F()->GetXaxis()->Set( + timeHisto[chid]->getTH1F()->GetXaxis()->GetNbins(), + timeHisto[chid]->getTH1F()->GetXaxis()->GetXmin() + new_time_offset, // new Xmin + timeHisto[chid]->getTH1F()->GetXaxis()->GetXmax() + new_time_offset); // new Xmax + timeHisto[chid]->getTH1F()->ResetStats(); + + time_info[key] = {new_time_offset, timePrecision}; + } + + auto calibPPS = PPSTimingCalibration(formula, params, time_info); + // write the object + edm::Service poolDbService; + poolDbService->writeOne(&calibPPS, poolDbService->currentTime(), "PPSTimingCalibrationRcd"); +} + +//------------------------------------------------------------------------------ + +void PPSDiamondSampicTimingCalibrationPCLHarvester::dqmEndJob(DQMStore::IBooker& iBooker, DQMStore::IGetter& iGetter) { + iBooker.cd(); + iBooker.setCurrentFolder(dqmDir_); + if (jsonCalibFile_.empty()) + calibDb(iGetter); + else + calibJson(iGetter); +} + +//------------------------------------------------------------------------------ + +void PPSDiamondSampicTimingCalibrationPCLHarvester::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { + edm::ParameterSetDescription desc; + desc.add("timingCalibrationTag", "GlobalTag:DiamondSampicCalibration") + ->setComment("input tag for timing calibration retrieval"); + desc.add("dqmDir", "AlCaReco/PPSDiamondSampicTimingCalibrationPCL") + ->setComment("input path for the various DQM plots"); + desc.add("minEntries", 1)->setComment("minimal number of hits to extract calibration"); + desc.add("jsonCalibFile", "") + ->setComment( + "input path for json file containing calibration, if none, calibration will be obtained from db instead"); + desc.add("jsonOutputPath", "offset_cal.json")->setComment("output path for the new json calibration"); + descriptions.add("PPSDiamondSampicTimingCalibrationPCLHarvester", desc); +} + +DEFINE_FWK_MODULE(PPSDiamondSampicTimingCalibrationPCLHarvester); \ No newline at end of file diff --git a/CalibPPS/TimingCalibration/plugins/PPSDiamondSampicTimingCalibrationPCLWorker.cc b/CalibPPS/TimingCalibration/plugins/PPSDiamondSampicTimingCalibrationPCLWorker.cc new file mode 100644 index 0000000000000..71c3b20357778 --- /dev/null +++ b/CalibPPS/TimingCalibration/plugins/PPSDiamondSampicTimingCalibrationPCLWorker.cc @@ -0,0 +1,155 @@ +// -*- C++ -*- +// +// Package: CalibPPS/TimingCalibration/PPSDiamondSampicTimingCalibrationPCLWorker +// Class: PPSDiamondSampicTimingCalibrationPCLWorker +// +/**\class PPSDiamondSampicTimingCalibrationPCLWorker PPSDiamondSampicTimingCalibrationPCLWorker.cc CalibPPS/TimingCalibration/PPSDiamondSampicTimingCalibrationPCLWorker/plugins/PPSDiamondSampicTimingCalibrationPCLWorker.cc + + Description: Worker of DiamondSampic calibration which produces RecHitsTime histograms and id mapping for the Harvester + + Implementation: + [Notes on implementation] +*/ +// +// Original Author: Christopher Misan +// Created: Mon, 26 Jul 2021 07:37:13 GMT +// +// + +#include + +#include "FWCore/Framework/interface/Frameworkfwd.h" +#include "DQMServices/Core/interface/DQMGlobalEDAnalyzer.h" + +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/MakerMacros.h" + +#include "FWCore/ParameterSet/interface/ParameterSet.h" + +#include "Geometry/VeryForwardGeometryBuilder/interface/CTPPSGeometry.h" +#include "Geometry/Records/interface/VeryForwardRealGeometryRecord.h" + +#include "DataFormats/CTPPSDetId/interface/TotemTimingDetId.h" +#include "DataFormats/CTPPSDetId/interface/CTPPSDiamondDetId.h" +#include "DataFormats/CTPPSDigi/interface/TotemTimingDigi.h" +#include "DataFormats/CTPPSReco/interface/TotemTimingRecHit.h" +#include "DataFormats/Common/interface/DetSetVector.h" + +//------------------------------------------------------------------------------ + +struct Histograms_PPSDiamondSampicTimingCalibrationPCLWorker { + std::unordered_map timeHisto; + std::unordered_map db; + std::unordered_map sampic; + std::unordered_map channel; +}; + +class PPSDiamondSampicTimingCalibrationPCLWorker + : public DQMGlobalEDAnalyzer { +public: + explicit PPSDiamondSampicTimingCalibrationPCLWorker(const edm::ParameterSet&); + ~PPSDiamondSampicTimingCalibrationPCLWorker() override; + + static void fillDescriptions(edm::ConfigurationDescriptions& descriptions); + +private: + void bookHistograms(DQMStore::IBooker&, + edm::Run const&, + edm::EventSetup const&, + Histograms_PPSDiamondSampicTimingCalibrationPCLWorker&) const override; + + void dqmAnalyze(edm::Event const&, + edm::EventSetup const&, + Histograms_PPSDiamondSampicTimingCalibrationPCLWorker const&) const override; + + // ------------ member data ------------ + edm::EDGetTokenT> totemTimingDigiToken_; + edm::EDGetTokenT> totemTimingRecHitToken_; + edm::ESGetToken geomEsToken_; + std::string folder_; +}; + +//------------------------------------------------------------------------------ + +PPSDiamondSampicTimingCalibrationPCLWorker::PPSDiamondSampicTimingCalibrationPCLWorker(const edm::ParameterSet& iConfig) + : totemTimingDigiToken_( + consumes>(iConfig.getParameter("totemTimingDigiTag"))), + totemTimingRecHitToken_( + consumes>(iConfig.getParameter("totemTimingRecHitTag"))), + geomEsToken_(esConsumes()), + folder_(iConfig.getParameter("folder")) {} + +PPSDiamondSampicTimingCalibrationPCLWorker::~PPSDiamondSampicTimingCalibrationPCLWorker() {} + +//------------------------------------------------------------------------------ + +void PPSDiamondSampicTimingCalibrationPCLWorker::dqmAnalyze( + edm::Event const& iEvent, + edm::EventSetup const& iSetup, + Histograms_PPSDiamondSampicTimingCalibrationPCLWorker const& histos) const { + edm::Handle> timingDigi; + edm::Handle> timingRecHit; + iEvent.getByToken(totemTimingRecHitToken_, timingRecHit); + iEvent.getByToken(totemTimingDigiToken_, timingDigi); + + if (timingRecHit->empty()) { + edm::LogWarning("PPSDiamondSampicTimingCalibrationPCLWorker:dqmAnalyze") + << "No rechits retrieved from the event content."; + return; + } + + for (const auto& digis : *timingDigi) { + const CTPPSDiamondDetId detId(digis.detId()); + for (const auto& digi : digis) { + histos.db.at(detId.rawId())->Fill(digi.hardwareBoardId()); + histos.sampic.at(detId.rawId())->Fill(digi.hardwareSampicId()); + histos.channel.at(detId.rawId())->Fill(digi.hardwareChannelId()); + } + } + + for (const auto& recHits : *timingRecHit) { + const CTPPSDiamondDetId detId(recHits.detId()); + for (const auto& recHit : recHits) + histos.timeHisto.at(detId.rawId())->Fill(recHit.time()); + } +} + +//------------------------------------------------------------------------------ + +void PPSDiamondSampicTimingCalibrationPCLWorker::bookHistograms( + DQMStore::IBooker& ibook, + edm::Run const& run, + edm::EventSetup const& iSetup, + Histograms_PPSDiamondSampicTimingCalibrationPCLWorker& histos) const { + ibook.setCurrentFolder(folder_); + std::string ch_name; + const auto& geom = iSetup.getData(geomEsToken_); + for (auto it = geom.beginSensor(); it != geom.endSensor(); ++it) { + if (!CTPPSDiamondDetId::check(it->first)) + continue; + const CTPPSDiamondDetId detid(it->first); + + std::string path; + detid.channelName(path, CTPPSDiamondDetId::nPath); + detid.channelName(ch_name); + histos.timeHisto[detid.rawId()] = ibook.book1D(path + "/" + ch_name, ch_name, 500, -25, 25); + histos.db[detid.rawId()] = ibook.bookInt(path + "/" + ch_name + "db"); + histos.sampic[detid.rawId()] = ibook.bookInt(path + "/" + ch_name + "sampic"); + histos.channel[detid.rawId()] = ibook.bookInt(path + "/" + ch_name + "channel"); + } +} + +//------------------------------------------------------------------------------ + +void PPSDiamondSampicTimingCalibrationPCLWorker::fillDescriptions(edm::ConfigurationDescriptions& descriptions) { + edm::ParameterSetDescription desc; + desc.add("totemTimingDigiTag", edm::InputTag("totemTimingRawToDigi", "TotemTiming")) + ->setComment("input tag for the PPS diamond detectors digi"); + desc.add("totemTimingRecHitTag", edm::InputTag("totemTimingRecHits")) + ->setComment("input tag for the PPS diamond detectors rechits"); + desc.add("folder", "AlCaReco/PPSDiamondSampicTimingCalibrationPCL") + ->setComment("output path for the various DQM plots"); + descriptions.add("PPSDiamondSampicTimingCalibrationPCLWorker", desc); +} + +DEFINE_FWK_MODULE(PPSDiamondSampicTimingCalibrationPCLWorker); diff --git a/CalibPPS/TimingCalibration/python/ALCARECOPPSCalTrackBasedSel_Output_cff.py b/CalibPPS/TimingCalibration/python/ALCARECOPPSCalTrackBasedSel_Output_cff.py index 1415b8c708f01..20bee7ec6c60e 100644 --- a/CalibPPS/TimingCalibration/python/ALCARECOPPSCalTrackBasedSel_Output_cff.py +++ b/CalibPPS/TimingCalibration/python/ALCARECOPPSCalTrackBasedSel_Output_cff.py @@ -6,7 +6,9 @@ ), outputCommands = cms.untracked.vstring( 'keep *_ALCARECOPPSCalTrackBasedSel_*_*', - 'keep *_ctppsDiamondRawToDigi_*_*' + 'keep *_ctppsDiamondRawToDigi_*_*', + 'keep *_totemTimingRawToDigi_*_*' + # will be updated to add the spatial alignment required collections ) ) diff --git a/CalibPPS/TimingCalibration/python/ALCARECOPPSDiamondSampicTimingCalibHarvester_cff.py b/CalibPPS/TimingCalibration/python/ALCARECOPPSDiamondSampicTimingCalibHarvester_cff.py new file mode 100644 index 0000000000000..1c6ecf70c86a7 --- /dev/null +++ b/CalibPPS/TimingCalibration/python/ALCARECOPPSDiamondSampicTimingCalibHarvester_cff.py @@ -0,0 +1,13 @@ +import FWCore.ParameterSet.Config as cms + +from Geometry.VeryForwardGeometry.geometryRPFromDB_cfi import * +from CalibPPS.TimingCalibration.PPSDiamondSampicTimingCalibrationPCLHarvester_cfi import * + + +DQMStore = cms.Service("DQMStore") + +from DQMServices.Core.DQMEDHarvester import DQMEDHarvester +dqmEnv = DQMEDHarvester('DQMHarvestingMetadata', + subSystemFolder=cms.untracked.string('AlCaReco/PPSDiamondSampicTimingCalibrationPCL/AlignedChannels')) + +ALCAHARVESTPPSDiamondSampicTimingCalibration = cms.Sequence(PPSDiamondSampicTimingCalibrationPCLHarvester + dqmEnv) diff --git a/CalibPPS/TimingCalibration/python/ALCARECOPPSDiamondSampicTimingCalib_Output_cff.py b/CalibPPS/TimingCalibration/python/ALCARECOPPSDiamondSampicTimingCalib_Output_cff.py new file mode 100644 index 0000000000000..d86911e241cde --- /dev/null +++ b/CalibPPS/TimingCalibration/python/ALCARECOPPSDiamondSampicTimingCalib_Output_cff.py @@ -0,0 +1,13 @@ +import FWCore.ParameterSet.Config as cms + +OutALCARECOPPSDiamondSampicTimingCalib_noDrop = cms.PSet( + SelectEvents = cms.untracked.PSet( + SelectEvents = cms.vstring('pathALCARECOPPSDiamondSampicTimingCalib') + ), + outputCommands = cms.untracked.vstring( + 'keep *_MEtoEDMConvertPPSDiamondSampicTimingCalib_*_*', + ) +) + +OutALCARECOPPSDiamondSampicTimingCalib = OutALCARECOPPSDiamondSampicTimingCalib_noDrop.clone() +OutALCARECOPPSDiamondSampicTimingCalib.outputCommands.insert(0, 'drop *') diff --git a/CalibPPS/TimingCalibration/python/ALCARECOPPSDiamondSampicTimingCalib_cff.py b/CalibPPS/TimingCalibration/python/ALCARECOPPSDiamondSampicTimingCalib_cff.py new file mode 100644 index 0000000000000..060a364dced8e --- /dev/null +++ b/CalibPPS/TimingCalibration/python/ALCARECOPPSDiamondSampicTimingCalib_cff.py @@ -0,0 +1,18 @@ +import FWCore.ParameterSet.Config as cms + +from RecoPPS.Configuration.recoCTPPS_cff import diamondSampicLocalReconstructionTask +from CalibPPS.TimingCalibration.PPSDiamondSampicTimingCalibrationPCLWorker_cfi import PPSDiamondSampicTimingCalibrationPCLWorker +from DQMServices.Core.DQMEDAnalyzer import DQMEDAnalyzer + +MEtoEDMConvertPPSDiamondSampicTimingCalib = cms.EDProducer('MEtoEDMConverter', + Name = cms.untracked.string('MEtoEDMConverter'), + Verbosity = cms.untracked.int32(0), + Frequency = cms.untracked.int32(50), + MEPathToSave = cms.untracked.string('AlCaReco/PPSDiamondSampicTimingCalibrationPCL') +) + +taskALCARECOPPSDiamondSampicTimingCalib = cms.Task( + diamondSampicLocalReconstructionTask, + PPSDiamondSampicTimingCalibrationPCLWorker, + MEtoEDMConvertPPSDiamondSampicTimingCalib +) diff --git a/CalibPPS/TimingCalibration/test/DiamondSampicCalibrationHarvester_cfg.py b/CalibPPS/TimingCalibration/test/DiamondSampicCalibrationHarvester_cfg.py new file mode 100644 index 0000000000000..62477a79dae75 --- /dev/null +++ b/CalibPPS/TimingCalibration/test/DiamondSampicCalibrationHarvester_cfg.py @@ -0,0 +1,68 @@ +import FWCore.ParameterSet.Config as cms + +process = cms.Process("harvester") + +process.load("FWCore.MessageService.MessageLogger_cfi") + +process.maxEvents = cms.untracked.PSet( input = cms.untracked.int32(-1) ) + +process.load('Configuration.StandardSequences.Services_cff') +process.load('Configuration.EventContent.EventContent_cff') +process.load('Configuration.StandardSequences.FrontierConditions_GlobalTag_cff') +from Configuration.AlCa.GlobalTag import GlobalTag +process.GlobalTag = GlobalTag(process.GlobalTag, '113X_dataRun3_Prompt_PPStestSampicPCL_v1') + +# Source (histograms) +process.source = cms.Source("DQMRootSource", + fileNames = cms.untracked.vstring("file:worker_output.root"), +) + +# output service for database +process.load('CondCore.CondDB.CondDB_cfi') +process.CondDB.connect = 'sqlite_file:ppsDiamondSampicTiming_calibration.sqlite' # SQLite output + +process.PoolDBOutputService = cms.Service('PoolDBOutputService', + process.CondDB, + timetype = cms.untracked.string('runnumber'), + toPut = cms.VPSet( + cms.PSet( + record = cms.string('PPSTimingCalibrationRcd'), + tag = cms.string('DiamondSampicCalibration'), + ) + ) +) + +################ +#geometry +################ +process.load('Geometry.VeryForwardGeometry.geometryRPFromDD_2021_cfi') + +process.load("CalibPPS.TimingCalibration.PPSDiamondSampicTimingCalibrationPCLHarvester_cfi") +#process.PPSDiamondSampicTimingCalibrationPCLHarvester.jsonCalibFile=cms.string("initial.cal.json") + +# load DQM framework +process.load("DQMServices.Core.DQMStore_cfi") +process.load("DQMServices.Components.DQMEnvironment_cfi") +process.dqmEnv.subSystemFolder = "CalibPPS" +process.dqmSaver.convention = 'Offline' +process.dqmSaver.workflow = "/CalibPPS/TimingCalibration/CMSSW_12_0_0_pre2" +process.dqmSaver.saveByRun = -1 +process.dqmSaver.saveAtJobEnd = True +process.dqmSaver.forceRunNumber = 999999 + +process.p = cms.Path( + process.PPSDiamondSampicTimingCalibrationPCLHarvester +) + +process.end_path = cms.EndPath( + process.dqmEnv + + process.dqmSaver +) + +process.schedule = cms.Schedule( + process.p, + process.end_path +) + + + diff --git a/CalibPPS/TimingCalibration/test/DiamondSampicCalibrationWorker_cfg.py b/CalibPPS/TimingCalibration/test/DiamondSampicCalibrationWorker_cfg.py new file mode 100644 index 0000000000000..b1b58bb878e33 --- /dev/null +++ b/CalibPPS/TimingCalibration/test/DiamondSampicCalibrationWorker_cfg.py @@ -0,0 +1,83 @@ +import FWCore.ParameterSet.Config as cms + +process = cms.Process("worker") + +process.load("FWCore.MessageService.MessageLogger_cfi") +process.load('RecoPPS.Local.totemTimingLocalReconstruction_cff') +process.source = cms.Source("EmptySource") +process.maxEvents = cms.untracked.PSet( input = cms.untracked.int32(10000) ) + +process.load('Configuration.StandardSequences.Services_cff') +process.load('Configuration.EventContent.EventContent_cff') +process.load('Configuration.StandardSequences.FrontierConditions_GlobalTag_cff') +from Configuration.AlCa.GlobalTag import GlobalTag +process.GlobalTag = GlobalTag(process.GlobalTag, '113X_dataRun3_Prompt_PPStestSampicPCL_v1') + +################ +#digi converter +################ +process.totemTimingRawToDigi = cms.EDProducer('DiamondSampicDigiProducer', + #input path of the testbeam data + sampicFilesVec=cms.vstring("/eos/cms/store/group/dpg_ctpps/comm_ctpps/201905_DesyTestbeam/MergedDev/Ntuple_runsampic_159_runtelescope_636.root"), + ################ + #channel mapping + ################ + idsMapping = cms.VPSet( + cms.PSet(detId = cms.vuint32(2054160384,2054553600,2056257536,2056650752), treeChId = cms.uint32(8)), + cms.PSet(detId = cms.vuint32(2054164480,2054557696,2056261632,2056654848), treeChId = cms.uint32(9)), + cms.PSet(detId = cms.vuint32(2054168576,2054561792,2056265728,2056658944), treeChId = cms.uint32(10)), + cms.PSet(detId = cms.vuint32(2054172672,2054565888,2056269824,2056663040), treeChId = cms.uint32(11)), + cms.PSet(detId = cms.vuint32(2054176768,2054569984,2056273920,2056667136), treeChId = cms.uint32(12)), + cms.PSet(detId = cms.vuint32(2054180864,2054574080,2056278016,2056671232), treeChId = cms.uint32(13)), + cms.PSet(detId = cms.vuint32(2054184960,2054578176,2056282112,2056675328), treeChId = cms.uint32(14)), + cms.PSet(detId = cms.vuint32(2054189056,2054582272,2056286208,2056679424), treeChId = cms.uint32(15)), + cms.PSet(detId = cms.vuint32(2054193152,2054586368,2056290304,2056683520), treeChId = cms.uint32(16)), + cms.PSet(detId = cms.vuint32(2054197248,2054590464,2056294400,2056687616), treeChId = cms.uint32(17)), + cms.PSet(detId = cms.vuint32(2054201344,2054594560,2056298496,2056691712), treeChId = cms.uint32(18)), + cms.PSet(detId = cms.vuint32(2054205440,2054598656,2056302592,2056695808), treeChId = cms.uint32(19)), + + cms.PSet(detId = cms.vuint32(2054291456,2054422528,2056388608,2056519680), treeChId = cms.uint32(20)), + cms.PSet(detId = cms.vuint32(2054295552,2054426624,2056392704,2056523776), treeChId = cms.uint32(21)), + cms.PSet(detId = cms.vuint32(2054299648,2054430720,2056396800,2056527872), treeChId = cms.uint32(22)), + cms.PSet(detId = cms.vuint32(2054303744,2054434816,2056400896,2056531968), treeChId = cms.uint32(23)), + cms.PSet(detId = cms.vuint32(2054307840,2054438912,2056404992,2056536064), treeChId = cms.uint32(24)), + cms.PSet(detId = cms.vuint32(2054311936,2054443008,2056409088,2056540160), treeChId = cms.uint32(25)), + cms.PSet(detId = cms.vuint32(2054316032,2054447104,2056413184,2056544256), treeChId = cms.uint32(26)), + cms.PSet(detId = cms.vuint32(2054320128,2054451200,2056417280,2056548352), treeChId = cms.uint32(27)), + cms.PSet(detId = cms.vuint32(2054324224,2054455296,2056421376,2056552448), treeChId = cms.uint32(28)), + cms.PSet(detId = cms.vuint32(2054328320,2054459392,2056425472,2056556544), treeChId = cms.uint32(29)), + cms.PSet(detId = cms.vuint32(2054332416,2054463488,2056429568,2056560640), treeChId = cms.uint32(30)), + cms.PSet(detId = cms.vuint32(2054336512,2054467584,2056433664,2056564736), treeChId = cms.uint32(31)) + + ) +) + +process.totemTimingRecHits.mergeTimePeaks= cms.bool(False) +process.totemTimingRecHits.timingCalibrationTag= cms.string('GlobalTag:DiamondSampicCalibration') +################ +#geometry +################ +process.load('Geometry.VeryForwardGeometry.geometryRPFromDD_2021_cfi') + +process.load("CalibPPS.TimingCalibration.PPSDiamondSampicTimingCalibrationPCLWorker_cfi") +process.DQMStore = cms.Service("DQMStore") + +process.dqmOutput = cms.OutputModule("DQMRootOutputModule", + fileName = cms.untracked.string("worker_output.root") +) + + +process.path = cms.Path( + process.totemTimingRawToDigi* + process.diamondSampicLocalReconstruction* + process.PPSDiamondSampicTimingCalibrationPCLWorker +) + +process.end_path = cms.EndPath( + process.dqmOutput +) + +process.schedule = cms.Schedule( + process.path, + process.end_path +) diff --git a/CalibPPS/TimingCalibration/test/runDiamondSampicCalibration b/CalibPPS/TimingCalibration/test/runDiamondSampicCalibration new file mode 100755 index 0000000000000..3c8c617d6009a --- /dev/null +++ b/CalibPPS/TimingCalibration/test/runDiamondSampicCalibration @@ -0,0 +1,7 @@ +#!/bin/bash + +#---------------------------------------------------------------------------------------------------- + +cmsRun DiamondSampicCalibrationWorker_cfg.py &> log_DiamondSampicCalibrationWorker.log & +wait +cmsRun DiamondSampicCalibrationHarvester_cfg.py &> log_DiamondSampicCalibrationHarvester.log & diff --git a/Configuration/AlCa/python/autoPCL.py b/Configuration/AlCa/python/autoPCL.py index e2825741730a0..5d5a06f7ecd14 100644 --- a/Configuration/AlCa/python/autoPCL.py +++ b/Configuration/AlCa/python/autoPCL.py @@ -8,5 +8,6 @@ 'PromptCalibProdSiStripGainsAAG' : 'SiStripGainsAAG', 'PromptCalibProdLumiPCC': 'LumiPCC', 'PromptCalibProdSiPixel' : 'SiPixelQuality', - 'PromptCalibProdPPS' : 'PPSTimingCalibration' + 'PromptCalibProdPPS' : 'PPSTimingCalibration', + 'PromptCalibProdPPSDiamondSampic' : 'PPSDiamondSampicTimingCalibration' } diff --git a/Configuration/EventContent/python/AlCaRecoOutput_cff.py b/Configuration/EventContent/python/AlCaRecoOutput_cff.py index aab0d9c3fab2f..63abee3b7bf78 100644 --- a/Configuration/EventContent/python/AlCaRecoOutput_cff.py +++ b/Configuration/EventContent/python/AlCaRecoOutput_cff.py @@ -141,6 +141,7 @@ ############################################################### from CalibPPS.TimingCalibration.ALCARECOPPSCalTrackBasedSel_Output_cff import * from CalibPPS.TimingCalibration.ALCARECOPPSTimingCalib_Output_cff import * +from CalibPPS.TimingCalibration.ALCARECOPPSDiamondSampicTimingCalib_Output_cff import * ############################################################### # stream for prompt-calibration @ Tier0 diff --git a/Configuration/StandardSequences/python/AlCaHarvesting_cff.py b/Configuration/StandardSequences/python/AlCaHarvesting_cff.py index 41604bb588ed0..3d4ced64d0675 100644 --- a/Configuration/StandardSequences/python/AlCaHarvesting_cff.py +++ b/Configuration/StandardSequences/python/AlCaHarvesting_cff.py @@ -11,6 +11,7 @@ from CalibTracker.SiPixelQuality.SiPixelStatusHarvester_cfi import * from CalibTracker.SiPixelQuality.DQMEventInfoSiPixelQuality_cff import * from CalibPPS.TimingCalibration.PPSTimingCalibrationHarvester_cff import * +from CalibPPS.TimingCalibration.ALCARECOPPSDiamondSampicTimingCalibHarvester_cff import * from Calibration.TkAlCaRecoProducers.PCLMetadataWriter_cfi import * @@ -220,9 +221,14 @@ ALCAHARVESTPPSTimingCalibration_metadata = cms.PSet(record = cms.untracked.string('PPSTimingCalibrationRcd')) ALCAHARVESTPPSTimingCalibration_dbOutput = cms.PSet(record = cms.string('PPSTimingCalibrationRcd'), tag = cms.string('PPSDiamondTimingCalibration_pcl'), - timetype = cms.untracked.string('lumiid') + timetype = cms.untracked.string('runnumber') ) +ALCAHARVESTPPSDiamondSampicTimingCalibration_metadata = cms.PSet(record = cms.untracked.string('PPSTimingCalibrationRcd_Sampic')) +ALCAHARVESTPPSDiamondSampicTimingCalibration_dbOutput = cms.PSet(record = cms.string('PPSTimingCalibrationRcd_Sampic'), + tag = cms.string('DiamondSampicCalibration'), + timetype = cms.untracked.string('runnumber')) + # define all the paths BeamSpotByRun = cms.Path(ALCAHARVESTBeamSpotByRun) BeamSpotByLumi = cms.Path(ALCAHARVESTBeamSpotByLumi) @@ -238,6 +244,7 @@ LumiPCC = cms.Path(ALCAHARVESTLumiPCC) SiPixelQuality = cms.Path(dqmEnvSiPixelQuality+ALCAHARVESTSiPixelQuality)#+siPixelPhase1DQMHarvester) PPSTimingCalibration = cms.Path(ALCAHARVESTPPSTimingCalibration) +PPSDiamondSampicTimingCalibration = cms.Path(ALCAHARVESTPPSDiamondSampicTimingCalibration) ALCAHARVESTDQMSaveAndMetadataWriter = cms.Path(dqmSaver+pclMetadataWriter) diff --git a/Configuration/StandardSequences/python/AlCaRecoStreams_cff.py b/Configuration/StandardSequences/python/AlCaRecoStreams_cff.py index 1ff1ca78ca02c..3f1bfea6f0a3d 100644 --- a/Configuration/StandardSequences/python/AlCaRecoStreams_cff.py +++ b/Configuration/StandardSequences/python/AlCaRecoStreams_cff.py @@ -125,6 +125,7 @@ # Timing calibration from CalibPPS.TimingCalibration.ALCARECOPPSCalTrackBasedSel_cff import * from CalibPPS.TimingCalibration.ALCARECOPPSTimingCalib_cff import * +from CalibPPS.TimingCalibration.ALCARECOPPSDiamondSampicTimingCalib_cff import * ############################################################### # nonbeam alcas @@ -226,6 +227,7 @@ pathALCARECOMuAlOverlapsGeneralTracks = cms.Path(seqALCARECOMuAlOverlapsGeneralTracks) pathALCARECORpcCalHLT = cms.Path(seqALCARECORpcCalHLT) pathALCARECOPPSTimingCalib = cms.Path(taskALCARECOPPSTimingCalib) +pathALCARECOPPSDiamondSampicTimingCalib = cms.Path(taskALCARECOPPSDiamondSampicTimingCalib) pathALCARECOTkAlBeamHalo = cms.Path(seqALCARECOTkAlBeamHalo*ALCARECOTkAlBeamHaloDQM) pathALCARECOMuAlBeamHaloOverlaps = cms.Path(seqALCARECOMuAlBeamHaloOverlaps) pathALCARECOMuAlBeamHalo = cms.Path(seqALCARECOMuAlBeamHalo) @@ -821,6 +823,15 @@ selectEvents = OutALCARECOPPSTimingCalib.SelectEvents, dataTier = cms.untracked.string('ALCARECO') ) + +ALCARECOStreamPPSDiamondSampicTimingCalib = cms.FilteredStream( + responsible = 'Christopher Misan', + name = 'PPSDiamondSampicTimingCalib', + paths = (pathALCARECOPPSDiamondSampicTimingCalib), + content = OutALCARECOPPSDiamondSampicTimingCalib.outputCommands, + selectEvents = OutALCARECOPPSDiamondSampicTimingCalib.SelectEvents, + dataTier = cms.untracked.string('ALCARECO') + ) ALCARECOStreamPromptCalibProd = cms.FilteredStream( responsible = 'Gianluca Cerminara', diff --git a/DQM/CTPPS/plugins/BuildFile.xml b/DQM/CTPPS/plugins/BuildFile.xml index f82346cffcbd3..6e804109707e8 100644 --- a/DQM/CTPPS/plugins/BuildFile.xml +++ b/DQM/CTPPS/plugins/BuildFile.xml @@ -13,4 +13,5 @@ + diff --git a/DQM/CTPPS/plugins/DiamondSampicCalibrationDQMSource.cc b/DQM/CTPPS/plugins/DiamondSampicCalibrationDQMSource.cc new file mode 100644 index 0000000000000..81a5cf0e4ba71 --- /dev/null +++ b/DQM/CTPPS/plugins/DiamondSampicCalibrationDQMSource.cc @@ -0,0 +1,300 @@ +// -*- C++ -*- +// +// Package: DQM/CTPPS/DiamondSampicCalibrationDQMSource +// Class: DiamondSampicCalibrationDQMSource +// +/**\class DiamondSampicCalibrationDQMSource DiamondSampicCalibrationDQMSource.cc SampicDigi/DiamondSampicCalibrationDQMSource/plugins/DiamondSampicCalibrationDQMSource.cc + + Description: DQM module for the diamond sampic offset calibration + + Implementation: + [Notes on implementation] +*/ +// +// Original Author: Christopher Misan +// Created: Mon, 24 Aug 2021 14:21:17 GMT +// +// + +#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 "CondFormats/PPSObjects/interface/PPSTimingCalibration.h" +#include "CondFormats/DataRecord/interface/PPSTimingCalibrationRcd.h" + +#include + +//---------------------------------------------------------------------------------------------------- + +class DiamondSampicCalibrationDQMSource : public DQMOneEDAnalyzer<> { +public: + DiamondSampicCalibrationDQMSource(const edm::ParameterSet &); + ~DiamondSampicCalibrationDQMSource() 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; + +private: + // Constants + 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; + + edm::EDGetTokenT> totemTimingDigiToken_; + edm::EDGetTokenT> tokenRecHit_; + edm::ESGetToken timingCalibrationToken_; + edm::ESGetToken geomEsToken_; + unsigned int verbosity_; + edm::TimeValue_t timeOfPreviousEvent_; + + float verticalShiftBot_, verticalShiftTop_; + std::unordered_map horizontalShiftOfDiamond_; + + /// plots related to the whole system + struct GlobalPlots { + GlobalPlots() {} + GlobalPlots(DQMStore::IBooker &ibooker); + }; + + GlobalPlots globalPlot_; + + /// plots related to one Diamond detector package + struct PotPlots { + // RecHits + MonitorElement *hitDistribution2d = nullptr; + MonitorElement *recHitTime = nullptr; + + PotPlots(){}; + PotPlots(DQMStore::IBooker &ibooker, unsigned int id); + }; + + std::unordered_map potPlots_; + + /// plots related to one Diamond plane + struct PlanePlots { + PlanePlots() {} + PlanePlots(DQMStore::IBooker &ibooker, unsigned int id); + }; + + std::unordered_map planePlots_; + + /// plots related to one Diamond channel + struct ChannelPlots { + // RecHits + MonitorElement *recHitTime = nullptr; + + ChannelPlots() {} + ChannelPlots(DQMStore::IBooker &ibooker, unsigned int id); + }; + + edm::ESHandle hTimingCalib_; + std::unordered_map channelPlots_; +}; + +//---------------------------------------------------------------------------------------------------- + +// Values for all constants +const double DiamondSampicCalibrationDQMSource::DISPLAY_RESOLUTION_FOR_HITS_MM = 0.05; +const double DiamondSampicCalibrationDQMSource::INV_DISPLAY_RESOLUTION_FOR_HITS_MM = + 1. / DISPLAY_RESOLUTION_FOR_HITS_MM; + +//---------------------------------------------------------------------------------------------------- + +DiamondSampicCalibrationDQMSource::GlobalPlots::GlobalPlots(DQMStore::IBooker &ibooker) { + ibooker.setCurrentFolder("CTPPS/TimingFastSilicon"); +} + +//---------------------------------------------------------------------------------------------------- + +DiamondSampicCalibrationDQMSource::PotPlots::PotPlots(DQMStore::IBooker &ibooker, unsigned int id) { + std::string path, title; + CTPPSDiamondDetId(id).rpName(path, CTPPSDiamondDetId::nPath); + ibooker.setCurrentFolder(path); + + CTPPSDiamondDetId(id).rpName(title, CTPPSDiamondDetId::nFull); + + 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); + + recHitTime = ibooker.book1D("recHit time", title + " time in the recHits; t (ns)", 500, -25, 25); +} + +//---------------------------------------------------------------------------------------------------- + +DiamondSampicCalibrationDQMSource::PlanePlots::PlanePlots(DQMStore::IBooker &ibooker, unsigned int id) { + std::string path, title; + CTPPSDiamondDetId(id).planeName(path, CTPPSDiamondDetId::nPath); + ibooker.setCurrentFolder(path); +} + +//---------------------------------------------------------------------------------------------------- + +DiamondSampicCalibrationDQMSource::ChannelPlots::ChannelPlots(DQMStore::IBooker &ibooker, unsigned int id) { + std::string path, title; + CTPPSDiamondDetId(id).channelName(path, CTPPSDiamondDetId::nPath); + ibooker.setCurrentFolder(path); + + CTPPSDiamondDetId(id).channelName(title, CTPPSDiamondDetId::nFull); + recHitTime = ibooker.book1D("recHit Time", title + " recHit Time; t (ns)", 500, -25, 25); +} + +//---------------------------------------------------------------------------------------------------- + +DiamondSampicCalibrationDQMSource::DiamondSampicCalibrationDQMSource(const edm::ParameterSet &ps) + : totemTimingDigiToken_( + consumes>(ps.getParameter("totemTimingDigiTag"))), + tokenRecHit_(consumes>(ps.getParameter("tagRecHits"))), + timingCalibrationToken_(esConsumes()), + geomEsToken_(esConsumes()), + verbosity_(ps.getUntrackedParameter("verbosity", 0)), + timeOfPreviousEvent_(0) {} + +//---------------------------------------------------------------------------------------------------- + +DiamondSampicCalibrationDQMSource::~DiamondSampicCalibrationDQMSource() {} + +//---------------------------------------------------------------------------------------------------- + +void DiamondSampicCalibrationDQMSource::dqmBeginRun(const edm::Run &iRun, const edm::EventSetup &iSetup) { + // Get detector shifts from the geometry (if present) + const auto &geom = iSetup.getData(geomEsToken_); + 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"; + } +} + +//---------------------------------------------------------------------------------------------------- + +void DiamondSampicCalibrationDQMSource::bookHistograms(DQMStore::IBooker &ibooker, + const edm::Run &, + const edm::EventSetup &iSetup) { + ibooker.cd(); + ibooker.setCurrentFolder("CTPPS"); + + globalPlot_ = GlobalPlots(ibooker); + const auto &geom = iSetup.getData(geomEsToken_); + for (auto it = geom.beginSensor(); it != geom.endSensor(); ++it) { + if (!CTPPSDiamondDetId::check(it->first)) + continue; + const CTPPSDiamondDetId detid(it->first); + + const CTPPSDiamondDetId rpId(detid.arm(), detid.station(), detid.rp()); + potPlots_[rpId] = PotPlots(ibooker, rpId); + + 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); + } + hTimingCalib_ = iSetup.getHandle(timingCalibrationToken_); +} + +//---------------------------------------------------------------------------------------------------- + +void DiamondSampicCalibrationDQMSource::analyze(const edm::Event &event, const edm::EventSetup &eventSetup) { + PPSTimingCalibration calib = *hTimingCalib_; + // get event setup data + edm::Handle> timingRecHits; + event.getByToken(tokenRecHit_, timingRecHits); + + edm::Handle> timingDigi; + event.getByToken(totemTimingDigiToken_, timingDigi); + + std::unordered_map detIdToHw; + + for (const auto &digis : *timingDigi) { + const CTPPSDiamondDetId detId(digis.detId()); + for (const auto &digi : digis) + detIdToHw[detId] = digi.hardwareId(); + } + + // Using TotemTimingDigi + std::set boardSet; + std::unordered_map channelsPerPlane; + std::unordered_map channelsPerPlaneWithTime; + + // 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)); + + //All plots with Time + if (rechit.time() != TotemTimingRecHit::NO_T_AVAILABLE) { + int db = (detIdToHw[detId] & 0xE0) >> 5; + int sampic = (detIdToHw[detId] & 0x10) >> 4; + int channel = (detIdToHw[detId] & 0x0F); + double offset = calib.timeOffset(db, sampic, channel); + potPlots_[detId_pot].recHitTime->Fill(rechit.time() + offset); + if (channelPlots_.find(detId) != channelPlots_.end()) + channelPlots_[detId].recHitTime->Fill(rechit.time() + offset); + } + } + } + } + // End RecHits + + timeOfPreviousEvent_ = event.time().value(); +} + +DEFINE_FWK_MODULE(DiamondSampicCalibrationDQMSource);