Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[nT2] DQM for the TOTEM nT2 detector #39159

Merged
merged 2 commits into from
Aug 31, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions DQM/CTPPS/BuildFile.xml
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
<use name="DataFormats/CTPPSDetId"/>
<use name="DataFormats/TotemReco"/>
<use name="FWCore/Utilities"/>
<use name="Geometry/ForwardGeometry"/>
<use name="dd4hep"/>
<use name="root"/>
<export>
<lib name="1"/>
</export>
37 changes: 37 additions & 0 deletions DQM/CTPPS/interface/TotemT2Segmentation.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/****************************************************************************
*
* This is a part of TOTEM offline software.
* Author:
* Laurent Forthomme
*
****************************************************************************/

#ifndef DQM_CTPPS_TotemT2Segmentation_h
#define DQM_CTPPS_TotemT2Segmentation_h

#include "DataFormats/CTPPSDetId/interface/TotemT2DetId.h"
#include "Geometry/ForwardGeometry/interface/TotemGeometry.h"

#include <unordered_map>
#include <vector>

class TotemGeometry;
class TH2D;

class TotemT2Segmentation {
public:
explicit TotemT2Segmentation(const TotemGeometry&, size_t, size_t);

void fill(TH2D*, const TotemT2DetId&, double value = 1.);

private:
std::vector<std::pair<short, short> > computeBins(const TotemT2DetId& detid) const;

const TotemGeometry geom_;
const size_t nbinsx_;
const size_t nbinsy_;

std::unordered_map<TotemT2DetId, std::vector<std::pair<short, short> > > bins_map_;
};

#endif
2 changes: 2 additions & 0 deletions DQM/CTPPS/plugins/BuildFile.xml
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@
<use name="FWCore/ParameterSet"/>
<use name="FWCore/Utilities"/>
<use name="DQMServices/Core"/>
<use name="DQM/CTPPS"/>
<use name="DataFormats/OnlineMetaData"/>
<use name="DataFormats/Common"/>
<use name="DataFormats/CTPPSDetId"/>
<use name="DataFormats/CTPPSDigi"/>
<use name="DataFormats/CTPPSReco"/>
<use name="DataFormats/ProtonReco"/>
<use name="Geometry/Records"/>
<use name="Geometry/ForwardGeometry"/>
<use name="Geometry/VeryForwardGeometryBuilder"/>
<use name="Geometry/VeryForwardRPTopology"/>
<use name="CondFormats/DataRecord"/>
Expand Down
285 changes: 285 additions & 0 deletions DQM/CTPPS/plugins/TotemT2DQMSource.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,285 @@
/****************************************************************************
*
* This is a part of TOTEM offline software.
* Author:
* Laurent Forthomme
* Arkadiusz Cwikla
*
****************************************************************************/

#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/ParameterSet/interface/ParameterSet.h"
#include "FWCore/Utilities/interface/InputTag.h"

#include "DQMServices/Core/interface/DQMEDAnalyzer.h"
#include "DQMServices/Core/interface/DQMStore.h"

#include "DataFormats/Common/interface/DetSetVectorNew.h"

#include "DataFormats/CTPPSDetId/interface/TotemT2DetId.h"
#include "DataFormats/TotemReco/interface/TotemT2Digi.h"
#include "DataFormats/TotemReco/interface/TotemT2RecHit.h"

#include "Geometry/Records/interface/TotemGeometryRcd.h"
#include "DQM/CTPPS/interface/TotemT2Segmentation.h"

#include <string>

class TotemT2DQMSource : public DQMEDAnalyzer {
public:
TotemT2DQMSource(const edm::ParameterSet&);
~TotemT2DQMSource() override = default;

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:
void fillActivePlanes(std::unordered_map<unsigned int, std::set<unsigned int>>&, const TotemT2DetId&);
void fillTriggerBitset(const TotemT2DetId&);
void clearTriggerBitset();
bool areChannelsTriggered(const TotemT2DetId&);
void bookErrorFlagsHistogram(DQMStore::IBooker&);
void fillErrorFlagsHistogram(const TotemT2Digi&);
void fillEdges(const TotemT2Digi&, const TotemT2DetId&);
void fillToT(const TotemT2RecHit&, const TotemT2DetId&);

const edm::ESGetToken<TotemGeometry, TotemGeometryRcd> geometryToken_;
const edm::EDGetTokenT<edmNew::DetSetVector<TotemT2Digi>> digiToken_;
const edm::EDGetTokenT<edmNew::DetSetVector<TotemT2RecHit>> rechitToken_;

std::unique_ptr<TotemT2Segmentation> segm_;

static constexpr double HPTDC_BIN_WIDTH_NS_ = 25. / 1024;
MonitorElement* HPTDCErrorFlags_2D_ = nullptr;

const unsigned int nbinsx_, nbinsy_;
const unsigned int windowsNum_;

struct SectorPlots {
MonitorElement* activePlanes = nullptr;
MonitorElement* activePlanesCount = nullptr;

MonitorElement* triggerEmulator = nullptr;
std::bitset<(TotemT2DetId::maxPlane + 1) * (TotemT2DetId::maxChannel + 1)> hitTilesArray;
static const unsigned int MINIMAL_TRIGGER = 3;

MonitorElement *leadingEdge = nullptr, *trailingEdge = nullptr, *timeOverTreshold = nullptr;

SectorPlots() = default;
SectorPlots(
DQMStore::IBooker& ibooker, unsigned int id, unsigned int nbinsx, unsigned int nbinsy, unsigned int windowsNum);
};

struct PlanePlots {
MonitorElement* digisMultiplicity = nullptr;
MonitorElement* rechitMultiplicity = nullptr;

PlanePlots() = default;
PlanePlots(DQMStore::IBooker& ibooker, unsigned int id, unsigned int nbinsx, unsigned int nbinsy);
};

std::unordered_map<unsigned int, SectorPlots> sectorPlots_;
std::unordered_map<unsigned int, PlanePlots> planePlots_;
};

TotemT2DQMSource::SectorPlots::SectorPlots(
DQMStore::IBooker& ibooker, unsigned int id, unsigned int nbinsx, unsigned int nbinsy, unsigned int windowsNum) {
std::string title, path;

TotemT2DetId(id).armName(path, TotemT2DetId::nPath);
ibooker.setCurrentFolder(path);

TotemT2DetId(id).armName(title, TotemT2DetId::nFull);

activePlanes = ibooker.book1D("active planes", title + " which planes are active;plane number", 8, -0.5, 7.5);

activePlanesCount = ibooker.book1D(
"number of active planes", title + " how many planes are active;number of active planes", 9, -0.5, 8.5);

triggerEmulator = ibooker.book2DD("trigger emulator",
title + " trigger emulator;arbitrary unit;arbitrary unit",
nbinsx,
-0.5,
double(nbinsx) - 0.5,
nbinsy,
-0.5,
double(nbinsy) - 0.5);
leadingEdge = ibooker.book1D(
"leading edge", title + " leading edge (DIGIs); leading edge (ns)", 25 * windowsNum, 0, 25 * windowsNum);
trailingEdge = ibooker.book1D(
"trailing edge", title + " trailing edge (DIGIs); trailing edge (ns)", 25 * windowsNum, 0, 25 * windowsNum);

timeOverTreshold = ibooker.book1D(
"time over threshold", title + " time over threshold (rechit);time over threshold (ns)", 250, -25, 100);
}

TotemT2DQMSource::PlanePlots::PlanePlots(DQMStore::IBooker& ibooker,
unsigned int id,
unsigned int nbinsx,
unsigned int nbinsy) {
std::string title, path;
TotemT2DetId(id).planeName(title, TotemT2DetId::nFull);
TotemT2DetId(id).planeName(path, TotemT2DetId::nPath);
ibooker.setCurrentFolder(path);

digisMultiplicity = ibooker.book2DD("digis multiplicity",
title + " digis multiplicity;arbitrary unit;arbitrary unit",
nbinsx,
-0.5,
double(nbinsx) - 0.5,
nbinsy,
-0.5,
double(nbinsy) - 0.5);
rechitMultiplicity = ibooker.book2DD("rechits multiplicity",
title + " rechits multiplicity;x;y",
nbinsx,
-0.5,
double(nbinsx) - 0.5,
nbinsy,
-0.5,
double(nbinsy) - 0.5);
}

TotemT2DQMSource::TotemT2DQMSource(const edm::ParameterSet& iConfig)
: geometryToken_(esConsumes<TotemGeometry, TotemGeometryRcd, edm::Transition::BeginRun>()),
digiToken_(consumes<edmNew::DetSetVector<TotemT2Digi>>(iConfig.getParameter<edm::InputTag>("digisTag"))),
rechitToken_(consumes<edmNew::DetSetVector<TotemT2RecHit>>(iConfig.getParameter<edm::InputTag>("rechitsTag"))),
nbinsx_(iConfig.getParameter<unsigned int>("nbinsx")),
nbinsy_(iConfig.getParameter<unsigned int>("nbinsy")),
windowsNum_(iConfig.getParameter<unsigned int>("windowsNum")) {}

void TotemT2DQMSource::dqmBeginRun(const edm::Run&, const edm::EventSetup&) {}

void TotemT2DQMSource::bookHistograms(DQMStore::IBooker& ibooker, const edm::Run&, const edm::EventSetup& iSetup) {
ibooker.cd();
ibooker.setCurrentFolder("TotemT2");

bookErrorFlagsHistogram(ibooker);

for (unsigned int arm = 0; arm <= CTPPSDetId::maxArm; ++arm) {
for (unsigned int pl = 0; pl <= TotemT2DetId::maxPlane; ++pl) {
const TotemT2DetId detid(arm, pl, 0);
const TotemT2DetId planeId(detid.planeId());
planePlots_[planeId] = PlanePlots(ibooker, planeId, nbinsx_, nbinsy_);
}
const TotemT2DetId detid(arm, 0, 0);
const TotemT2DetId secId(detid.armId());
sectorPlots_[secId] = SectorPlots(ibooker, secId, nbinsx_, nbinsy_, windowsNum_);
}

// build a segmentation helper for the size of histograms previously booked
segm_ = std::make_unique<TotemT2Segmentation>(iSetup.getData(geometryToken_), nbinsx_, nbinsy_);
}

void TotemT2DQMSource::analyze(const edm::Event& iEvent, const edm::EventSetup& iSetup) {
// fill digis information
for (const auto& ds_digis : iEvent.get(digiToken_)) {
const TotemT2DetId detid(ds_digis.detId());
const TotemT2DetId planeId(detid.planeId());
for (const auto& digi : ds_digis) {
segm_->fill(planePlots_[planeId].digisMultiplicity->getTH2D(), detid);
fillTriggerBitset(detid);
fillErrorFlagsHistogram(digi);
fillEdges(digi, detid);
}
}

// fill rechits information
std::unordered_map<unsigned int, std::set<unsigned int>> planes;
for (const auto& ds_rechits : iEvent.get(rechitToken_)) {
const TotemT2DetId detid(ds_rechits.detId());
const TotemT2DetId planeId(detid.planeId());
for (const auto& rechit : ds_rechits) {
segm_->fill(planePlots_[planeId].rechitMultiplicity->getTH2D(), detid);
fillToT(rechit, detid);
fillActivePlanes(planes, detid);
}
}

for (const auto& plt : sectorPlots_)
plt.second.activePlanesCount->Fill(planes[plt.first].size());

for (unsigned short arm = 0; arm <= CTPPSDetId::maxArm; ++arm)
for (unsigned short plane = 0; plane <= 1; ++plane)
for (unsigned short id = 0; id <= TotemT2DetId::maxChannel; ++id) {
const TotemT2DetId detid(arm, plane, id);
if (areChannelsTriggered(detid)) {
const TotemT2DetId secId(detid.armId());
segm_->fill(sectorPlots_[secId].triggerEmulator->getTH2D(), detid);
}
}

clearTriggerBitset();
}

void TotemT2DQMSource::fillActivePlanes(std::unordered_map<unsigned int, std::set<unsigned int>>& planes,
const TotemT2DetId& detid) {
const TotemT2DetId secId(detid.armId());
unsigned short pl = detid.plane();

planes[secId].insert(pl);

sectorPlots_[secId].activePlanes->Fill(pl);
}

void TotemT2DQMSource::fillTriggerBitset(const TotemT2DetId& detid) {
const TotemT2DetId secId(detid.armId());
unsigned short pl = detid.plane();
unsigned short ch = detid.channel();
sectorPlots_[secId].hitTilesArray[4 * pl + ch] = true;
}

void TotemT2DQMSource::clearTriggerBitset() {
for (auto& sectorPlot : sectorPlots_)
sectorPlot.second.hitTilesArray.reset();
}

bool TotemT2DQMSource::areChannelsTriggered(const TotemT2DetId& detid) {
unsigned int channel = detid.channel();

// prepare mask
std::bitset<(TotemT2DetId::maxPlane + 1) * (TotemT2DetId::maxChannel + 1)> mask;
// check if plane is even or not
unsigned int pl = detid.plane() % 2 == 0 ? 0 : 1;
// set only even or only odd plane bits for this channel
for (; pl <= TotemT2DetId::maxPlane; pl += 2)
mask[4 * pl + channel] = true;
const TotemT2DetId secId(detid.armId());
// check how many masked channels were hit
unsigned int triggeredChannelsNumber = (mask & sectorPlots_[secId].hitTilesArray).count();

return triggeredChannelsNumber >= SectorPlots::MINIMAL_TRIGGER;
}

void TotemT2DQMSource::bookErrorFlagsHistogram(DQMStore::IBooker& ibooker) {
HPTDCErrorFlags_2D_ = ibooker.book2D("HPTDC Errors", " HPTDC Errors?", 8, -0.5, 7.5, 2, -0.5, 1.5);
for (unsigned short error_index = 1; error_index <= 8; ++error_index)
HPTDCErrorFlags_2D_->setBinLabel(error_index, "Flag " + std::to_string(error_index));

int tmpIndex = 0;
HPTDCErrorFlags_2D_->setBinLabel(++tmpIndex, "some id 0", /* axis */ 2);
HPTDCErrorFlags_2D_->setBinLabel(++tmpIndex, "some id 1", /* axis */ 2);
}

void TotemT2DQMSource::fillErrorFlagsHistogram(const TotemT2Digi& digi) {
// placeholder for error hitogram filling
(void)digi;
}

void TotemT2DQMSource::fillEdges(const TotemT2Digi& digi, const TotemT2DetId& detid) {
const TotemT2DetId secId(detid.armId());
sectorPlots_[secId].leadingEdge->Fill(HPTDC_BIN_WIDTH_NS_ * digi.leadingEdge());
sectorPlots_[secId].trailingEdge->Fill(HPTDC_BIN_WIDTH_NS_ * digi.trailingEdge());
}

void TotemT2DQMSource::fillToT(const TotemT2RecHit& rechit, const TotemT2DetId& detid) {
const TotemT2DetId secId(detid.armId());
sectorPlots_[secId].timeOverTreshold->Fill(rechit.toT());
}

DEFINE_FWK_MODULE(TotemT2DQMSource);
12 changes: 12 additions & 0 deletions DQM/CTPPS/python/totemT2DQMSource_cfi.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import FWCore.ParameterSet.Config as cms

from DQMServices.Core.DQMEDAnalyzer import DQMEDAnalyzer
totemT2DQMSource = DQMEDAnalyzer('TotemT2DQMSource',
digisTag = cms.InputTag('totemT2Digis', 'TotemT2'),
rechitsTag = cms.InputTag('totemT2RecHits'),
nbinsx = cms.uint32(25),
nbinsy = cms.uint32(25),
windowsNum = cms.uint32(4),

perLSsaving = cms.untracked.bool(False), #driven by DQMServices/Core/python/DQMStore_cfi.py
)
Loading