ATLAS Offline Software
Loading...
Searching...
No Matches
MMTriggerTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
5#include "MMTriggerTool.h"
6
7namespace NSWL1 {
8
9 MMTriggerTool::MMTriggerTool( const std::string& type, const std::string& name, const IInterface* parent) :
10 base_class(type,name,parent) {}
11
13
14 ATH_MSG_DEBUG( name() << " configuration:");
15 ATH_MSG_DEBUG(" " << std::setw(32) << std::setfill('.') << std::setiosflags(std::ios::left) << m_mmDigitContainer.name() << m_mmDigitContainer.value());
16 ATH_MSG_DEBUG(" " << std::setw(32) << std::setfill('.') << std::setiosflags(std::ios::left) << m_doNtuple.name() << ((m_doNtuple)? "[True]":"[False]")
17 << std::setfill(' ') << std::setiosflags(std::ios::right) );
18
21 ATH_CHECK(m_keyMmDigitContainer.initialize());
22 ATH_CHECK(m_idHelperSvc.retrieve());
23 ATH_CHECK(m_detectorManagerKey.initialize());
24 ATH_CHECK(m_dcsKey.initialize(!m_isMC));
25
26 if(m_doNtuple and Gaudi::Concurrency::ConcurrencyFlags::numConcurrentEvents() > 1) {
27 ATH_MSG_ERROR("DoNtuple is not possible in multi-threaded mode");
28 return StatusCode::FAILURE;
29 }
30
32
33 return StatusCode::SUCCESS;
34 }
35
37 m_trigger_diamond_ntrig = std::make_shared<MuonVal::VectorBranch<unsigned int> >(tree, "MM_diamond_ntrig");
38 m_trigger_diamond_bc = std::make_shared<MuonVal::VectorBranch<int> >(tree, "MM_diamond_bc");
39 m_trigger_diamond_sector = std::make_shared<MuonVal::VectorBranch<char> >(tree, "MM_diamond_sector");
40 m_trigger_diamond_sectorPhi = std::make_shared<MuonVal::VectorBranch<int> >(tree, "MM_diamond_sectorPhi");
41 m_trigger_diamond_totalCount = std::make_shared<MuonVal::VectorBranch<unsigned int> >(tree, "MM_diamond_totalCount");
42 m_trigger_diamond_iX = std::make_shared<MuonVal::VectorBranch<int> >(tree, "MM_diamond_iX");
43 m_trigger_diamond_iU = std::make_shared<MuonVal::VectorBranch<int> >(tree, "MM_diamond_iU");
44 m_trigger_diamond_iV = std::make_shared<MuonVal::VectorBranch<int> >(tree, "MM_diamond_iV");
45 m_trigger_diamond_xCount = std::make_shared<MuonVal::VectorBranch<unsigned int> >(tree, "MM_diamond_xCount");
46 m_trigger_diamond_uCount = std::make_shared<MuonVal::VectorBranch<unsigned int> >(tree, "MM_diamond_uCount");
47 m_trigger_diamond_age = std::make_shared<MuonVal::VectorBranch<int> >(tree, "MM_diamond_age");
48 m_trigger_diamond_mx = std::make_shared<MuonVal::VectorBranch<double> >(tree, "MM_diamond_mx");
49 m_trigger_diamond_my = std::make_shared<MuonVal::VectorBranch<double> >(tree, "MM_diamond_my");
50 m_trigger_diamond_Uavg = std::make_shared<MuonVal::VectorBranch<double> >(tree, "MM_diamond_Uavg");
51 m_trigger_diamond_Vavg = std::make_shared<MuonVal::VectorBranch<double> >(tree, "MM_diamond_Vavg");
52 m_trigger_diamond_mxl = std::make_shared<MuonVal::VectorBranch<double> >(tree, "MM_diamond_mxl");
53 m_trigger_diamond_theta = std::make_shared<MuonVal::VectorBranch<double> >(tree, "MM_diamond_theta");
54 m_trigger_diamond_eta = std::make_shared<MuonVal::VectorBranch<double> >(tree, "MM_diamond_eta");
55 m_trigger_diamond_dtheta = std::make_shared<MuonVal::VectorBranch<double> >(tree, "MM_diamond_dtheta");
56 m_trigger_diamond_phi = std::make_shared<MuonVal::VectorBranch<double> >(tree, "MM_diamond_phi");
57 m_trigger_diamond_phiShf = std::make_shared<MuonVal::VectorBranch<double> >(tree, "MM_diamond_phiShf");
58 m_trigger_diamond_TP_phi_id = std::make_shared<MuonVal::VectorBranch<uint8_t> >(tree, "MM_diamond_TP_phi_id");
59 m_trigger_diamond_TP_R_id = std::make_shared<MuonVal::VectorBranch<uint8_t> >(tree, "MM_diamond_TP_R_id");
60 m_trigger_diamond_TP_dTheta_id = std::make_shared<MuonVal::VectorBranch<uint8_t> >(tree, "MM_diamond_TP_dTheta_id");
61 m_trigger_RZslopes = std::make_shared<MuonVal::VectorBranch<double> >(tree, "MM_RZslopes");
62 m_trigger_trueEtaRange = std::make_shared<MuonVal::VectorBranch<double> >(tree, "MM_trueEtaRange");
63 m_trigger_truePtRange = std::make_shared<MuonVal::VectorBranch<double> >(tree, "MM_truePtRange");
64 m_trigger_VMM = std::make_shared<MuonVal::VectorBranch<int> >(tree, "MM_VMM");
65 m_trigger_plane = std::make_shared<MuonVal::VectorBranch<int> >(tree, "MM_plane");
66 m_trigger_station = std::make_shared<MuonVal::VectorBranch<int> >(tree, "MM_station");
67 m_trigger_strip = std::make_shared<MuonVal::VectorBranch<int> >(tree, "MM_strip");
68 m_trigger_slope = std::make_shared<MuonVal::VectorBranch<double> >(tree, "MM_slope");
69 m_trigger_trueThe = std::make_shared<MuonVal::VectorBranch<double> >(tree, "MM_trueThe");
70 m_trigger_truePhi = std::make_shared<MuonVal::VectorBranch<double> >(tree, "MM_truePhi");
71 m_trigger_trueDth = std::make_shared<MuonVal::VectorBranch<double> >(tree, "MM_trueDth");
72 m_trigger_trueEtaEnt = std::make_shared<MuonVal::VectorBranch<double> >(tree, "MM_trueEtaEnt");
73 m_trigger_trueTheEnt = std::make_shared<MuonVal::VectorBranch<double> >(tree, "MM_trueTheEnt");
74 m_trigger_truePhiEnt = std::make_shared<MuonVal::VectorBranch<double> >(tree, "MM_truePhiEnt");
75 m_trigger_trueEtaPos = std::make_shared<MuonVal::VectorBranch<double> >(tree, "MM_trueEtaPos");
76 m_trigger_trueThePos = std::make_shared<MuonVal::VectorBranch<double> >(tree, "MM_trueThePos");
77 m_trigger_truePhiPos = std::make_shared<MuonVal::VectorBranch<double> >(tree, "MM_truePhiPos");
78
79 tree.addBranch(m_trigger_diamond_ntrig);
80 tree.addBranch(m_trigger_diamond_bc);
81 tree.addBranch(m_trigger_diamond_sector);
82 tree.addBranch(m_trigger_diamond_sectorPhi);
83 tree.addBranch(m_trigger_diamond_totalCount);
84 tree.addBranch(m_trigger_diamond_iX);
85 tree.addBranch(m_trigger_diamond_iU);
86 tree.addBranch(m_trigger_diamond_iV);
87 tree.addBranch(m_trigger_diamond_xCount);
88 tree.addBranch(m_trigger_diamond_uCount);
89 tree.addBranch(m_trigger_diamond_age);
90 tree.addBranch(m_trigger_diamond_mx);
91 tree.addBranch(m_trigger_diamond_my);
92 tree.addBranch(m_trigger_diamond_Uavg);
93 tree.addBranch(m_trigger_diamond_Vavg);
94 tree.addBranch(m_trigger_diamond_mxl);
95 tree.addBranch(m_trigger_diamond_theta);
96 tree.addBranch(m_trigger_diamond_eta);
97 tree.addBranch(m_trigger_diamond_dtheta);
98 tree.addBranch(m_trigger_diamond_phi);
99 tree.addBranch(m_trigger_diamond_phiShf);
100 tree.addBranch(m_trigger_diamond_TP_phi_id);
101 tree.addBranch(m_trigger_diamond_TP_R_id);
102 tree.addBranch(m_trigger_diamond_TP_dTheta_id);
103 tree.addBranch(m_trigger_RZslopes);
104 tree.addBranch(m_trigger_trueEtaRange);
105 tree.addBranch(m_trigger_truePtRange);
106 tree.addBranch(m_trigger_VMM);
107 tree.addBranch(m_trigger_plane);
108 tree.addBranch(m_trigger_station);
109 tree.addBranch(m_trigger_strip);
110 tree.addBranch(m_trigger_slope);
111 tree.addBranch(m_trigger_trueThe);
112 tree.addBranch(m_trigger_truePhi);
113 tree.addBranch(m_trigger_trueDth);
114 tree.addBranch(m_trigger_trueEtaEnt);
115 tree.addBranch(m_trigger_trueTheEnt);
116 tree.addBranch(m_trigger_truePhiEnt);
117 tree.addBranch(m_trigger_trueEtaPos);
118 tree.addBranch(m_trigger_trueThePos);
119 tree.addBranch(m_trigger_truePhiPos);
120 return StatusCode::SUCCESS;
121 }
122
123 StatusCode MMTriggerTool::runTrigger(const EventContext& ctx, Muon::NSW_TrigRawDataContainer* rdo, const bool do_MMDiamonds) const {
124
125 uint64_t event = ctx.eventID().event_number();
126 ATH_MSG_DEBUG("********************************************************* EVENT NUMBER = " << event);
127
129 if(!detManager.isValid()){
130 ATH_MSG_ERROR("Failed to retrieve the MuonDetectorManager conditions object");
131 return StatusCode::FAILURE;
132 }
133
134 const McEventCollection* ptrMcEventCollection = nullptr;
135 const TrackRecordCollection* ptrMuonEntryLayer = nullptr;
136 if(m_isMC){
137 SG::ReadHandle<McEventCollection> readMcEventCollection( m_keyMcEventCollection, ctx );
138 if( !readMcEventCollection.isValid() ){
139 ATH_MSG_ERROR("Cannot retrieve McEventCollection");
140 return StatusCode::FAILURE;
141 }
142 if(m_doTruth) ptrMcEventCollection = readMcEventCollection.cptr();
144 if( !readMuonEntryLayer.isValid() ){
145 ATH_MSG_ERROR("Cannot retrieve MuonEntryLayer");
146 return StatusCode::FAILURE;
147 }
148 if(m_doTruth and m_doNtuple) {
149 ptrMuonEntryLayer = readMuonEntryLayer.cptr();
151 std::map<std::pair<uint64_t, unsigned int>,evInf_entry> Event_Info;
152 ATH_CHECK(load.getTruthInfo(ctx, ptrMcEventCollection, ptrMuonEntryLayer, Event_Info));
153
154 // Extract truth info, if available
155 for (const auto &it : Event_Info) {
156 m_trigger_trueEtaRange->push_back(it.second.eta_ip);
157 m_trigger_truePtRange->push_back(it.second.pt);
158 m_trigger_trueThe->push_back(it.second.theta_ip);
159 m_trigger_truePhi->push_back(it.second.phi_ip);
160 m_trigger_trueDth->push_back(it.second.dtheta); // theta_pos-theta_ent
161 m_trigger_trueEtaPos->push_back(it.second.eta_pos);
162 m_trigger_trueThePos->push_back(it.second.theta_pos);
163 m_trigger_truePhiPos->push_back(it.second.phi_pos);
164 m_trigger_trueEtaEnt->push_back(it.second.eta_ent);
165 m_trigger_trueTheEnt->push_back(it.second.theta_ent);
166 m_trigger_truePhiEnt->push_back(it.second.phi_ent);
167 }
168 }
169 }
170
171 SG::ReadHandle<MmDigitContainer> readMmDigitContainer( m_keyMmDigitContainer, ctx );
172 if( !readMmDigitContainer.isValid() ){
173 ATH_MSG_ERROR("Cannot retrieve MmDigitContainer");
174 return StatusCode::FAILURE;
175 }
176
177 const NswDcsDbData* dcsData = nullptr;
178 if(!m_isMC) {
179 SG::ReadCondHandle<NswDcsDbData> dcsDataHandle{m_dcsKey, ctx};
180 if(!dcsDataHandle.isValid()) {
181 ATH_MSG_ERROR("Failed to retrieve DCS data while running on data");
182 return StatusCode::FAILURE;
183 }
184 dcsData = dcsDataHandle.cptr();
185 }
186
187 for (const MmDigitCollection* digitCollection : *readMmDigitContainer) {
188
189 std::vector<std::shared_ptr<MMT_Hit> > ev_hits;
190 for (const MmDigit* digit : *digitCollection) {
191 const Identifier id = digit->identify();
192 if (not m_idHelperSvc->isMM(id)) continue;
193
194 if(!m_isMC) {
195 if(!dcsData->isConnectedChannel(id) or !dcsData->isGood(ctx, id) or !dcsData->isGoodHv(id) or !dcsData->isGoodEltx(id)) continue;
196 bool disabled = false;
197 if(!dcsData->isGoodTDaq(ctx,id,disabled)) continue;
198 }
199
200 const std::string stationName = m_idHelperSvc->chamberNameString(id);
201 const int stationEta = m_idHelperSvc->stationEta(id);
202 const int stationPhi = m_idHelperSvc->stationPhi(id);
203 const int sector = m_idHelperSvc->sector(id);
204 const int multiplet = m_idHelperSvc->mmIdHelper().multilayer(id);
205 const int gasGap = m_idHelperSvc->mmIdHelper().gasGap(id);
206
207 const int channel = m_idHelperSvc->mmIdHelper().channel(id);
208 // Checking whether strip exceeds allowed ranges
209 const MuonGM::MMReadoutElement* readout = detManager->getMMReadoutElement(id);
210 if (channel < 1 or channel > (readout->getDesign(id))->totalStrips) continue;
211
212 const float stripTime = digit->stripResponseTime();
213 // Checking positive digitization time
214 if (stripTime < 0.) continue;
215 const int BC = std::ceil(stripTime/25.);
216 ev_hits.emplace_back(std::make_shared<MMT_Hit>(id, stationName, stationEta, stationPhi, sector, multiplet, gasGap, channel, stripTime, BC, detManager.cptr()));
217
218 if (ev_hits.back()->infSlope()) {
219 ATH_MSG_WARNING("Infinite slope, removing hit");
220 ev_hits.pop_back();
221 continue;
222 }
223 if (m_doNtuple) {
224 m_trigger_VMM->push_back(ev_hits.back()->getVMM());
225 m_trigger_plane->push_back(ev_hits.back()->getPlane());
226 m_trigger_station->push_back(ev_hits.back()->getStationEta());
227 m_trigger_strip->push_back(ev_hits.back()->getChannel());
228 m_trigger_RZslopes->push_back(ev_hits.back()->getRZSlope());
229 }
230 }
231
232 // Go ahead when hits are more than X+UV thresholds
233 if (do_MMDiamonds and ev_hits.size() >= (m_diamond->getXthreshold()+m_diamond->getUVthreshold())) {
234 const bool isLarge = (std::ranges::all_of(ev_hits, [](const auto &hit) { return hit->getSector() == 'L'; }));
235 const char sector = (isLarge) ? 'L' : 'S';
236 const char side = (std::ranges::all_of(ev_hits, [](const auto &hit) { return hit->getStationEta() < 0; })) ? 'C' : 'A';
237 const int sectorPhi = ev_hits[0]->getSectorPhi();
238 const bool allSectorPhi = (std::ranges::all_of(ev_hits, [&](const auto &hit) { return hit->getSectorPhi() == sectorPhi; }));
239 if (not allSectorPhi) {
240 ATH_MSG_ERROR("Available digits belongs to different sectors IDs, unable to assign an unique ID in output RDO");
241 return StatusCode::FAILURE;
242 }
243 const bool isEta1 = (std::ranges::all_of(ev_hits, [](const auto &hit) { return std::abs(hit->getStationEta()) == 1; }));
244
245 // Setup roads
246 std::vector<MMT_Road> ev_roads;
247 m_diamond->createRoads(ev_roads, isLarge, isEta1);
248
249 // Evaluate coincidences
250 std::vector<slope_t> diamondSlopes;
251 m_diamond->findDiamonds(ev_hits, ev_roads, diamondSlopes, sectorPhi);
252
253 // Store output, if any, in debug ntuple (if enabled) and in trigger RDO
254 if (not diamondSlopes.empty()) {
255 if (m_doNtuple) {
256 m_trigger_diamond_ntrig->push_back(diamondSlopes.size());
257 for (const auto &slope : diamondSlopes) {
258 m_trigger_diamond_sector->push_back(sector);
259 m_trigger_diamond_sectorPhi->push_back(sectorPhi);
260 m_trigger_diamond_bc->push_back(slope.BC);
261 m_trigger_diamond_totalCount->push_back(slope.totalCount);
262 m_trigger_diamond_xCount->push_back(slope.xCount);
263 m_trigger_diamond_uCount->push_back(slope.uCount);
264 m_trigger_diamond_iX->push_back(slope.iRoad);
265 m_trigger_diamond_iU->push_back(slope.iRoadu);
266 m_trigger_diamond_iV->push_back(slope.iRoadv);
267 m_trigger_diamond_age->push_back(slope.age);
268 m_trigger_diamond_mx->push_back(slope.mx);
269 m_trigger_diamond_my->push_back(slope.my);
270 m_trigger_diamond_Uavg->push_back(slope.uavg);
271 m_trigger_diamond_Vavg->push_back(slope.vavg);
272 m_trigger_diamond_mxl->push_back(slope.mxl);
273 m_trigger_diamond_theta->push_back(slope.theta);
274 m_trigger_diamond_eta->push_back(slope.eta);
275 m_trigger_diamond_dtheta->push_back(slope.dtheta);
276 m_trigger_diamond_phi->push_back(slope.phi);
277 m_trigger_diamond_phiShf->push_back(slope.phiShf);
278 }
279 }
280
281 // MM RDO filling below
282 std::vector<int> slopeBC;
283 for (const auto &slope : diamondSlopes) slopeBC.push_back(slope.BC);
284 std::ranges::sort(slopeBC);
285 slopeBC.erase( std::unique(slopeBC.begin(), slopeBC.end()), slopeBC.end() );
286 for (const auto bc : slopeBC) {
287 Muon::NSW_TrigRawData* trigRawData = new Muon::NSW_TrigRawData(sectorPhi-1, side, bc);
288
289 for (const auto &slope : diamondSlopes) {
290 if (bc == slope.BC) {
292
293 // Phi-id - here use local phi (not phiShf)
294 uint8_t phi_id = 0;
295 if (slope.phi > m_phiMax || slope.phi < m_phiMin) trigRawDataSegment->setPhiIndex(phi_id);
296 else {
297 uint8_t nPhi = (1<<m_phiBits) -2; // To accomodate the new phi-id encoding prescription around 0
298 float phiSteps = (m_phiMax - m_phiMin)/nPhi;
299 for (uint8_t i=0; i<nPhi; i++) {
300 if ((slope.phi) < (m_phiMin+i*phiSteps)) {
301 phi_id = i;
302 break;
303 }
304 }
305 trigRawDataSegment->setPhiIndex(phi_id);
306 }
307 if (m_doNtuple) m_trigger_diamond_TP_phi_id->push_back(phi_id);
308
309 // R-id
310 double extrapolatedR = 7824.46*std::abs(std::tan(slope.theta)); // The Z plane is a fixed value, taken from SL-TP documentation
311 uint8_t R_id = 0;
312 if (extrapolatedR > m_rMax || extrapolatedR < m_rMin) trigRawDataSegment->setRIndex(R_id);
313 else {
314 uint8_t nR = (1<<m_rBits) -1;
315 float Rsteps = (m_rMax - m_rMin)/nR;
316 for (uint8_t j=0; j<nR; j++) {
317 if (extrapolatedR < (m_rMin+j*Rsteps)) {
318 R_id = j;
319 break;
320 }
321 }
322 trigRawDataSegment->setRIndex(R_id);
323 }
324 if (m_doNtuple) m_trigger_diamond_TP_R_id->push_back(R_id);
325
326 // DeltaTheta-id
327 uint8_t dTheta_id = 0;
328 if (slope.dtheta > m_dThetaMax || slope.dtheta < m_dThetaMin) trigRawDataSegment->setDeltaTheta(dTheta_id);
329 else {
330 uint8_t ndTheta = (1<<m_dThetaBits) -1;
331 float dThetaSteps = (m_dThetaMax - m_dThetaMin)/ndTheta;
332 for (uint8_t k=0; k<ndTheta; k++) {
333 if ((slope.dtheta) < (m_dThetaMin+k*dThetaSteps)) {
334 dTheta_id = k;
335 break;
336 }
337 }
338 trigRawDataSegment->setDeltaTheta(dTheta_id);
339 }
340 if (m_doNtuple) m_trigger_diamond_TP_dTheta_id->push_back(dTheta_id);
341
342 // Low R-resolution bit
343 trigRawDataSegment->setLowRes(slope.lowRes);
344
345 trigRawData->push_back(trigRawDataSegment);
346 }
347 }
348 rdo->push_back(trigRawData);
349 }
350 }
351 }
352 else {
353 ATH_MSG_DEBUG("Available hits are " << ev_hits.size() << ", less than X+UV threshold, skipping digit collection");
354 }
355 }
356
357 return StatusCode::SUCCESS;
358 }
359}//end namespace
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
AtlasHitsVector< TrackRecord > TrackRecordCollection
value_type push_back(value_type pElem)
Add an element to the end of the collection.
This defines the McEventCollection, which is really just an ObjectVector of McEvent objectsFile: Gene...
An MMReadoutElement corresponds to a single STGC module; therefore typicaly a barrel muon station con...
const MuonChannelDesign * getDesign(const Identifier &id) const
returns the MuonChannelDesign class for the given identifier
void setDeltaTheta(uint8_t deltaTheta)
Gaudi::Property< int > m_diamOverlapStereoDown
Gaudi::Property< float > m_rMax
Gaudi::Property< int > m_diamXthreshold
MMTriggerTool(const std::string &type, const std::string &name, const IInterface *parent)
Gaudi::Property< float > m_phiMax
Gaudi::Property< float > m_dThetaMax
Gaudi::Property< float > m_phiMin
ServiceHandle< Muon::IMuonIdHelperSvc > m_idHelperSvc
Gaudi::Property< int > m_diamUVthreshold
Gaudi::Property< int > m_rBits
SG::ReadCondHandleKey< MuonGM::MuonDetectorManager > m_detectorManagerKey
virtual StatusCode initialize() override
Gaudi::Property< int > m_phiBits
StatusCode attachBranches(MuonVal::MuonTesterTree &tree) override
std::unique_ptr< MMT_Diamond > m_diamond
Gaudi::Property< int > m_diamOverlapEtaUp
Gaudi::Property< bool > m_doNtuple
Gaudi::Property< int > m_dThetaBits
Gaudi::Property< float > m_rMin
Gaudi::Property< std::string > m_mmDigitContainer
Gaudi::Property< int > m_diamOverlapStereoUp
SG::ReadHandleKey< MmDigitContainer > m_keyMmDigitContainer
StatusCode runTrigger(const EventContext &ctx, Muon::NSW_TrigRawDataContainer *rdo, const bool do_MMDiamonds) const override
Gaudi::Property< float > m_dThetaMin
SG::ReadHandleKey< McEventCollection > m_keyMcEventCollection
Gaudi::Property< bool > m_uv
Gaudi::Property< bool > m_doTruth
SG::ReadHandleKey< TrackRecordCollection > m_keyMuonEntryLayer
Gaudi::Property< bool > m_isMC
Gaudi::Property< int > m_diamRoadSize
Gaudi::Property< int > m_diamOverlapEtaDown
SG::ReadCondHandleKey< NswDcsDbData > m_dcsKey
bool isGoodEltx(const Identifier &channelId) const
bool isGood(const EventContext &ctx, const Identifier &channelId, bool issTgcQ1OuterHv=false) const
Returns whether the channel is alive, i.e. DCS state on, etc...
bool isConnectedChannel(const Identifier &channelId) const
bool isGoodHv(const Identifier &channelId, bool issTgcQ1OuterHv=false) const
bool isGoodTDaq(const EventContext &ctx, const Identifier &channelId, bool &permanentlyDisabled) const
const_pointer_type cptr()
virtual bool isValid() override final
Can the handle be successfully dereferenced?
const_pointer_type cptr()
Dereference the pointer.
PadEmulatorCoincidences.
DataModel_detail::iterator< DVL > unique(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of unique for DataVector/List.
TChain * tree