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);