ATLAS Offline Software
Loading...
Searching...
No Matches
SCTHitEffMonAlg.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3*/
4
5#include "SCTHitEffMonAlg.h"
6
7// Athena
13
14// InDet
19// Conditions
23
25
26// Track
27#include "TrkSurfaces/Surface.h"
30#include "TrkTrack/Track.h"
32
33// SCT
34#include "SCT_NameFormatter.h"
36
37// std and STL includes
38#include <algorithm>
39#include <array>
40#include <cmath>
41#include <limits> // std::numeric_limits
42#include <memory>
43#include <sstream>
44
45// #include "TRandom.h" // Only for Testing
46
47using namespace SCT_Monitoring;
48
49namespace {// anonymous namespace for functions at file scope
50 static const bool testOffline{false};
51
52 template< typename T > Identifier
53 surfaceOnTrackIdentifier(const T& tsos, const bool useTrackParameters = true) {
54 Identifier result; // default constructor produces invalid value
55 const Trk::MeasurementBase* mesb{tsos->measurementOnTrack()};
56
57 if (mesb and mesb->associatedSurface().associatedDetectorElement()) {
59 } else if (useTrackParameters and tsos->trackParameters()) {
60 result = tsos->trackParameters()->associatedSurface().associatedDetectorElementIdentifier();
61 }
62 return result;
63 }
64
65 constexpr double radianDegrees{180. / M_PI};
66
67 static const double stripWidth{79.95e-3}; // in mm
68
69 static const std::array < std::string, N_REGIONS > regionNames = {
70 "SCTHitEffMonitorEC", "SCTHitEffMonitorB", "SCTHitEffMonitorEA"
71 };
72
73}// namespace end
74
75SCTHitEffMonAlg::SCTHitEffMonAlg(const std::string& name, ISvcLocator* pSvcLocator)
76 :AthMonitorAlgorithm(name,pSvcLocator) {
77}
78
80 ATH_MSG_INFO("Initializing SCTHitEffMonAlg");
81
82 ATH_CHECK(detStore()->retrieve(m_sctId, "SCT_ID"));
83 ATH_CHECK(detStore()->retrieve(m_pixelId, "PixelID"));
84 ATH_CHECK(detStore()->retrieve(m_trtId, "TRT_ID"));
85
87 ATH_MSG_INFO("Retrieved pull calculator tool " << m_residualPullCalculator);
88
89 ATH_CHECK(m_holeSearchTool.retrieve());
90 ATH_MSG_INFO("Retrieved hole search tool " << m_holeSearchTool);
91
92 ATH_CHECK(m_rotcreator.retrieve());
93
94 ATH_MSG_INFO("Retrieved tool " << m_rotcreator);
95 ATH_CHECK( m_bunchCrossingKey.initialize());
96 ATH_CHECK(m_configConditions.retrieve());
97
98 m_path = (m_useIDGlobal) ? ("/InDetGlobal/") : ("");
99 ATH_MSG_INFO("End");
100
101 if ((m_minSCTHits == -1) and (m_minTRTHits == -1) and (m_minOtherHits == -1)) {
102 if (m_isCosmic) {
103 m_minTRTHits = 45;
104 m_minSCTHits = 7;
105 m_minOtherHits = 5;
106 } else {
107 m_minTRTHits = 30;
108 m_minSCTHits = 4;
109 m_minOtherHits = 3;
110 }
111 }
112
114 ATH_CHECK( m_TrackName.initialize() );
115 ATH_CHECK( m_sctContainerName.initialize() );
116
117 ATH_CHECK(m_SCTDetEleCollKey.initialize());
118 ATH_CHECK(m_fieldCondObjInputKey.initialize());
119
121}
122
123
124int SCTHitEffMonAlg::becIdxLayer2Index(const int becIdx, const int layer) const {
125 switch( becIdx ) {
127 return layer;
129 return layer + SCT_Monitoring::N_DISKS;
132 default:
133 return -1;
134 }
135}
136
137int SCTHitEffMonAlg::getWaferIndex(const int barrel_ec, const int layer_disk, const int side) const {
138 int waferIndex = -1;
139 if (barrel_ec == BARREL) {
140 // corresponds to the waferIndex of B3 side0
141 waferIndex = 0;
142 } else if (barrel_ec == ENDCAP_A) {
143 // corresponds to the waferIndex of EA0 side0
144 waferIndex = N_BARRELS*N_SIDES;
145 } else if (barrel_ec == ENDCAP_C) {
146 // corresponds to the waferIndex of EC0 side0
147 waferIndex = N_BARRELS*N_SIDES + N_ENDCAPS*N_SIDES;
148 } else {
149 ATH_MSG_WARNING("The barrel_bc index" << barrel_ec << " is not defined.");
150 return waferIndex;
151 }
152 return waferIndex + layer_disk * N_SIDES + side;
153}
154
156 const Trk::TrackParameters* trkParam,
157 const InDet::SCT_ClusterContainer* p_sctclcontainer) const {
158 double trackHitResidual{-999.};
159
160 if (trkParam==nullptr) {
161 ATH_MSG_WARNING("Not track parameters found. Returning default residual value.");
162 return trackHitResidual;
163 }
164 IdentifierHash idh{m_sctId->wafer_hash(surfaceID)};
165 auto containerIterator{p_sctclcontainer->indexFindPtr(idh)};
166 if (containerIterator != nullptr) {
167 for (const InDet::SCT_Cluster* cluster: *containerIterator) {
168 if ((cluster==nullptr) or (cluster->detectorElement()==nullptr)) {
169 ATH_MSG_WARNING("nullptr to RIO or detElement");
170 continue;
171 }
172 if (surfaceID == m_sctId->wafer_id(cluster->detectorElement()->identify())) {
173 const Trk::PrepRawData* rioo{dynamic_cast<const Trk::PrepRawData *>(cluster)};
174 std::unique_ptr<const Trk::RIO_OnTrack> rio{m_rotcreator->correct(*rioo, *trkParam, Gaudi::Hive::currentContext())};
175 if (not m_residualPullCalculator.empty()) {
176 std::optional<Trk::ResidualPull> residualPull{m_residualPullCalculator->residualPull(rio.get(), trkParam,
178 if (not residualPull) continue;
179 if (std::abs(residualPull->residual()[Trk::loc1]) < std::abs(trackHitResidual)) {
180 trackHitResidual = residualPull->residual()[Trk::loc1];
181 }
182 }
183 }
184 }
185 }
186 return trackHitResidual;
187}
188
189StatusCode
191 const Identifier id,
193 double& theta,
194 double& phi) const {
195 phi = 90.;
196 theta = 90.;
197
198 const Identifier waferId{m_sctId->wafer_id(id)};
199 const IdentifierHash waferHash{m_sctId->wafer_hash(waferId)};
200 const InDetDD::SiDetectorElement* element{elements->getDetectorElement(waferHash)};
201 if (not element) {
202 ATH_MSG_VERBOSE("findAnglesToWaferSurface: failed to find detector element for id = " << m_sctId->print_to_string(id));
203 return StatusCode::FAILURE;
204 }
205 double pNormal{mom.dot(element->normal())};
206 double pEta{mom.dot(element->etaAxis())};
207 double pPhi{mom.dot(element->phiAxis())};
208 if (pPhi < 0.) {
209 phi = -90.;
210 }
211 if (pEta < 0.) {
212 theta = -90.;
213 }
214 if (pNormal != 0.) {
215 phi = std::atan(pPhi / pNormal) * radianDegrees;
216 theta = std::atan(pEta / pNormal) * radianDegrees;
217 }
218 return StatusCode::SUCCESS;
219}
220
221int SCTHitEffMonAlg::previousChip(double xl, int side, bool swap) const {
222 double xLeftEdge{xl + N_STRIPS / 2. * stripWidth}; // xl defined wrt center of module, convert to edge of module
223 int chipPos{static_cast<int>(xLeftEdge / (stripWidth * N_STRIPS) * N_CHIPS)};
224
225 if (side == 0) {
226 chipPos = swap ? 5 - chipPos : chipPos;
227 } else {
228 chipPos = swap ? 11 - chipPos : 6 + chipPos;
229 }
230 return chipPos;
231}
232
233StatusCode SCTHitEffMonAlg::failCut(bool value, const std::string & name) const {
234 if (value) {
235 ATH_MSG_VERBOSE("Passed " << name);
236 return StatusCode::FAILURE;
237 }
238 ATH_MSG_VERBOSE("Failed " << name);
239 return StatusCode::SUCCESS;
240}
241
242StatusCode SCTHitEffMonAlg::fillHistograms(const EventContext& ctx) const {
243 ATH_MSG_VERBOSE("SCTHitEffMonTool::fillHistograms()");
244
245 const std::map<Identifier, unsigned int>* badChips{nullptr};
246 if (m_vetoBadChips) {
247 badChips = m_configConditions->badChips(ctx);
248 }
249
250 double timecor{-20.};
251 if (m_useTRTPhase or m_isCosmic) {
252 SG::ReadHandle<ComTime> theComTime{m_comTimeName, ctx};
253 if (theComTime.isValid()) {
254 timecor = theComTime->getTime();
255 ATH_MSG_VERBOSE("Retrieved ComTime object with name " << m_comTimeName.key() << " found: Time = " << timecor);
256 } else {
257 timecor = -18.;
258 ATH_MSG_WARNING("ComTime object not found with name " << m_comTimeName.key());
259 }
260 }
261 // If we are going to use TRT phase in anger, need run-dependent corrections.
262 const EventIDBase& pEvent{ctx.eventID()};
263 unsigned BCID{pEvent.bunch_crossing_id()};
265 if (!bcidHdl.isValid()) {
266 ATH_MSG_ERROR( "Unable to retrieve BunchCrossing conditions object" );
267 return StatusCode::FAILURE;
268 }
269 const BunchCrossingCondData* bcData{*bcidHdl};
271
273 const AtlasFieldCacheCondObj* fieldCondObj{*fieldHandle};
274 if (fieldCondObj==nullptr) {
275 ATH_MSG_ERROR("AtlasFieldCacheCondObj cannot be retrieved.");
276 return StatusCode::RECOVERABLE;
277 }
278 MagField::AtlasFieldCache fieldCache;
279 fieldCondObj->getInitializedCache(fieldCache);
280 const bool solenoidOn{fieldCache.solenoidOn()};
281
282 // ---- First try if m_tracksName is a TrackCollection
284 if (not tracks.isValid()) {
285 ATH_MSG_WARNING("Tracks not found: " << tracks << " / " << m_TrackName.key());
286 return StatusCode::SUCCESS;
287 } else {
288 ATH_MSG_VERBOSE("Successfully retrieved " << m_TrackName.key() << " : " << tracks->size() << " items");
289 }
290
292 if (not p_sctclcontainer.isValid()) {
293 ATH_MSG_WARNING("SCT clusters container not found: " << m_sctContainerName.key());
294 return StatusCode::SUCCESS;
295 }
296
297 // cut on number of tracks (skip this cut for online)
299 if (failCut(tracks->size() <= m_maxTracks, "# of tracks cut")) {
300 return StatusCode::SUCCESS;
301 }
302 }
303
305 const InDetDD::SiDetectorElementCollection* elements{sctDetEle.retrieve()};
306 if (elements==nullptr) {
307 ATH_MSG_FATAL(m_SCTDetEleCollKey.fullKey() << " could not be retrieved in fillHistograms()");
308 return StatusCode::FAILURE;
309 }
310
311
312 // Loop over track collection to count tracks
313 for (const Trk::Track* pthisTrack: *tracks) {
314 if (pthisTrack==nullptr) {
315 continue;
316 }
317 if (failCut(pthisTrack and pthisTrack->trackParameters() and pthisTrack->trackParameters()->size(),
318 "track cut: presence")) {
319 continue;
320 }
321
322 if (m_insideOutOnly and failCut(pthisTrack->info().patternRecoInfo(Trk::TrackInfo::SiSPSeededFinder),
323 "track cut: inside-out only")) {
324 continue;
325 }
326 if (pthisTrack->perigeeParameters() == nullptr) {
327 continue;
328 }
329 const Trk::Perigee* perigee{pthisTrack->perigeeParameters()};
330 const AmgVector(5)& perigeeParameters{perigee->parameters()};
331 const double d0{perigeeParameters[Trk::d0]};
332 const double z0{perigeeParameters[Trk::z0]};
333 const double perigeeTheta{perigeeParameters[Trk::theta]};
334
335 if (solenoidOn and failCut(perigee->pT() >= m_minPt, "track cut: Min Pt")) {
336 continue;
337 }
338 if (not m_isCosmic and failCut(std::abs(d0) <= m_maxD0, "track cut: max D0")) {
339 continue;
340 }
341 if (m_maxZ0sinTheta and failCut(std::abs(z0 * sin(perigeeTheta)) <= m_maxZ0sinTheta, "track cut: Max Z0sinTheta")) {
342 continue;
343 }
344 }
345
346 // Loop over original track collection
347 for (const Trk::Track* pthisTrack: *tracks) {
348
349 // First, go through all cuts in this block
350 ATH_MSG_VERBOSE("Starting new track");
351 if (pthisTrack==nullptr) {
352 continue;
353 }
354 if (failCut(pthisTrack and pthisTrack->trackParameters() and pthisTrack->trackParameters()->size(),
355 "track cut: presence")) {
356 continue;
357 }
358
359 if (m_insideOutOnly and failCut(pthisTrack->info().patternRecoInfo(Trk::TrackInfo::SiSPSeededFinder),
360 "track cut: inside-out only")) {
361 continue;
362 }
363 if (pthisTrack->perigeeParameters() == nullptr) {
364 continue;
365 }
366 const Trk::Perigee* perigee{pthisTrack->perigeeParameters()};
367 const AmgVector(5)& perigeeParameters{perigee->parameters()};
368 const double d0{perigeeParameters[Trk::d0]};
369 const double z0{perigeeParameters[Trk::z0]};
370 const double perigeeTheta{perigeeParameters[Trk::theta]};
371
372 if (failCut(perigee->pT() >= m_minPt, "track cut: Min Pt")) {
373 continue;
374 }
375 if (not m_isCosmic and failCut(std::abs(d0) <= m_maxD0, "track cut: max D0")) {
376 continue;
377 }
378 if (m_maxZ0sinTheta and failCut(std::abs(z0 * sin(perigeeTheta)) <= m_maxZ0sinTheta, "track cut: Max Z0sinTheta")) {
379 continue;
380 }
381
382 const Trk::TrackSummary* summary{pthisTrack->trackSummary()};
383
384 if (summary and (summary->get(Trk::numberOfSCTHits) < 1)) {
385 continue;
386 }
387
388 std::unique_ptr<const Trk::Track> trackWithHoles(m_holeSearchTool->getTrackWithHoles(*pthisTrack));
389 if (not trackWithHoles) {
390 ATH_MSG_WARNING("trackWithHoles pointer is invalid");
391 continue;
392 }
393 ATH_MSG_VERBOSE("Found " << trackWithHoles->trackStateOnSurfaces()->size() << " states on track");
394
395 int NHits[N_REGIONS] = {
396 0, 0, 0
397 };
398 int pixelNHits{0};
399 int pixelNHoles{0};
400 int trtNHits{0};
401
402 int sctNHitsPerRegion[N_LAYERS_TOTAL*N_SIDES] = {0};
403 int sctNHolesPerRegion[N_LAYERS_TOTAL*N_SIDES] = {0};
404 // Above two variables hold the number of hits for each SCT disk / layer.
405 // [N_LAYERS_TOTAL*N_SIDES(= 44)] indicates the waferIndex defined as below.
406 // 0- 7: B3 side0, B3 side1, B4 side0, ... B6 side1
407 // 8-25: EA0 side0, EA1 side1, ... EA8 side1
408 // 26-43: EC0 side0, EC1 side1, ... EC8 side1
409
410 std::map < Identifier, double > mapOfTrackHitResiduals;
411 double zmin = std::numeric_limits<float>::max();
412 double zmax = -std::numeric_limits<float>::max();
413 double zpos{0.};
414 float layerSide{-1};
415 float min_layerSide{999.};
416 float max_layerSide{-1.};
417 Identifier surfaceID;
418
419 // Loop over all TSOS (track state on surface) on track to check number of hits / holes on Pixel, SCT and TRT
420 for (const Trk::TrackStateOnSurface* tsos: *(trackWithHoles->trackStateOnSurfaces())) {
421 surfaceID = surfaceOnTrackIdentifier(tsos);
422
423 if (not surfaceID.is_valid()) {
424 continue;
425 }
426
427 // Check waferIndex; if the default value of -1 is kept, the corresponding TSOS is not associated with SCT.
428 int waferIndex = -1;
429 // Calculate waferIndex
430 if (m_sctId->is_sct(surfaceID)) {
431 waferIndex = getWaferIndex(m_sctId->barrel_ec(surfaceID),
432 m_sctId->layer_disk(surfaceID),
433 m_sctId->side(surfaceID));
434 }
435
437 if (m_pixelId->is_pixel(surfaceID)) {
438 pixelNHits++;
439 }
440 if (m_trtId->is_trt(surfaceID)) {
441 trtNHits++;
442 }
443 if (m_sctId->is_sct(surfaceID)) {
444 NHits[bec2Index(m_sctId->barrel_ec(surfaceID))]++;
445 mapOfTrackHitResiduals[surfaceID] = getResidual(surfaceID, tsos->trackParameters(), &*p_sctclcontainer);
446 sctNHitsPerRegion[waferIndex]++;
447 }
448 } else if (tsos->type(Trk::TrackStateOnSurface::Hole)) {
449 if (m_pixelId->is_pixel(surfaceID)) {
450 pixelNHoles++;
451 } else if (m_sctId->is_sct(surfaceID)) {
452 sctNHolesPerRegion[waferIndex]++;
453 }
454 }
455
456 if (tsos->type(Trk::TrackStateOnSurface::Measurement)) { // Determine zmin and zmax taking multiple
457 // hits/side into account
458 if (m_isCosmic) { // If this is cosmics use z, bad method but ok...
459 if (tsos->trackParameters()) {
460 zpos = tsos->trackParameters()->position().z();
461 zmax = std::max(zpos, zmax);
462 zmin = std::min(zpos, zmin);
463 } else {
464 ATH_MSG_WARNING("No track parameter found. Zmin and Zmax not recalculated.");
465 }
466 } else { // else use layer/side number : better but does not work for cosmics
467 if (m_sctId->is_sct(surfaceID)) {
468 layerSide = (m_sctId->barrel_ec(surfaceID) != 0) * N_BARRELS +
469 static_cast<float>(m_sctId->layer_disk(surfaceID)) + (static_cast<float>(m_sctId->side(surfaceID)) == 0) * 0.5;
470 min_layerSide = std::min(min_layerSide, layerSide);
471 max_layerSide = std::max(max_layerSide, layerSide);
472 } else if (m_pixelId->is_pixel(surfaceID)) {
473 min_layerSide = -1;
474 } else if (m_trtId->is_trt(surfaceID)) {
475 max_layerSide = N_BARRELS + N_ENDCAPS + 1;
476 }
477 }
478 }
479 }
480
481 int sctNHits{NHits[ENDCAP_C_INDEX] + NHits[BARREL_INDEX] + NHits[ENDCAP_A_INDEX]};
482 std::vector<bool> layersCrossedByTrack[N_REGIONS];
483 std::vector<int> nHolesOnLayer[N_REGIONS];
484 std::vector<int> nHolesDistOnLayer[N_REGIONS];
485 for (int i{0}; i < N_REGIONS; ++i) {
486 nHolesDistOnLayer[i].resize(n_layers[i] * 2, 0);
487 nHolesOnLayer[i].resize(n_layers[i] * 2, 0);
488 layersCrossedByTrack[i].resize(n_layers[i] * 2, false);
489 }
490
491 // Loop over all TSOS again; this time, to extract SCT-related hits and holes.
492 for (const Trk::TrackStateOnSurface* tsos: *(trackWithHoles->trackStateOnSurfaces())) {
493 ATH_MSG_VERBOSE("Starting new hit");
494 surfaceID = surfaceOnTrackIdentifier(tsos);
495
496 if (failCut(m_sctId->is_sct(surfaceID), "hit cut: is in SCT")) {
497 continue;
498 }
499
500
501 int side{m_sctId->side(surfaceID)};
502 int layer{m_sctId->layer_disk(surfaceID)};
503 int bec{m_sctId->barrel_ec(surfaceID)};
504 unsigned int isub{bec2Index(bec)};
505 ATH_MSG_VERBOSE("New SCT candidate: " << m_sctId->print_to_string(surfaceID));
506
507 int waferIndex = getWaferIndex(bec, layer, side);
508
509 Int_t sctNHitsExceptThisWafer{0};
510 Int_t sctNHolesExceptThisWafer{0};
511
512 for (Int_t i=0; i<N_LAYERS_TOTAL*N_SIDES; i++) {
513 if (i != waferIndex) {
514 sctNHitsExceptThisWafer += sctNHitsPerRegion[i];
515 sctNHolesExceptThisWafer += sctNHolesPerRegion[i];
516 }
517 }
518
519 // The track is required to satisfy:
520 // - Number of Si hits to be >= 8
521 // - Number of Si holes to be <= 1
522 // without counting on this TSOS object. (avoid tracking bias.)
523 if ((unsigned int)(sctNHitsExceptThisWafer + pixelNHits) < m_minSiHits) {
524 ATH_MSG_VERBOSE("This track is rejected due to the number of hits: " << sctNHitsExceptThisWafer * pixelNHits);
525 continue;
526 }
527 if ((unsigned int)(sctNHolesExceptThisWafer + pixelNHoles) > m_maxSiHoles) {
528 ATH_MSG_VERBOSE("This track is rejected due to the number of holes: " << sctNHolesExceptThisWafer * pixelNHoles);
529 continue;
530 }
531
532 std::string etaPhiSuffix = "_" + std::to_string(layer) + "_" + std::to_string(side);
533 const int detIndex{becIdxLayer2Index(isub, layer)};
534 if (detIndex == -1) {
535 ATH_MSG_WARNING("The detector region (barrel, endcap A, endcap C) could not be determined");
536 continue;
537 }
538 float eff{0.};
539 IdentifierHash sideHash{m_sctId->wafer_hash(surfaceID)};
540 Identifier module_id{m_sctId->module_id(surfaceID)};
541 float layerPlusHalfSide{static_cast<float>(layer) + static_cast<float>(side) * 0.5f};
542 float dedicated_layerPlusHalfSide{static_cast<float>(layer) + static_cast<float>((side + 1) % 2) * 0.5f};
543 const Trk::TrackParameters* trkParamOnSurface{tsos->trackParameters()};
544 double trackHitResidual{getResidual(surfaceID, trkParamOnSurface, &*p_sctclcontainer)};
545
546 float distCut{m_effdistcut};
547
549 eff = 1.;
550 } else if (tsos->type(Trk::TrackStateOnSurface::Hole) and (std::abs(trackHitResidual) < distCut)) {
551 eff = 1.;
552 }
553
554 bool otherFaceFound{false};
555 IdentifierHash otherSideHash;
556 Identifier otherSideSurfaceID;
557 IdContext context{m_sctId->wafer_context()};
558 m_sctId->get_other_side(sideHash, otherSideHash);
559 m_sctId->get_id(otherSideHash, otherSideSurfaceID, &context);
560 otherFaceFound = mapOfTrackHitResiduals.find(otherSideSurfaceID) != mapOfTrackHitResiduals.end();
561
562 int nOther{sctNHits};
564 --nOther;
565 }
566
567 // Get the track phi; we may cut on it.
568 double phiUp{90.};
569 double theta{90.};
570 if (trkParamOnSurface and (not findAnglesToWaferSurface(trkParamOnSurface->momentum(), surfaceID, elements, theta, phiUp))) {
571 ATH_MSG_WARNING("Error from findAngles");
572 }
573
574 if (m_useSCTorTRT) {
575 if (failCut(trtNHits >= m_minTRTHits or
576 sctNHits >= m_minSCTHits, "track cut: min TRT or SCT hits")) {
577 continue;
578 }
579 } else {
580 if (failCut(trtNHits >= m_minTRTHits, "track cut: min TRT hits")) {
581 continue;
582 }
583 if (failCut(sctNHits >= m_minSCTHits, "track cut: min SCT hits")) {
584 continue;
585 }
586 if (failCut(pixelNHits >= m_minPixelHits, "track cut: min Pixel hits")) {
587 continue;
588 }
589 }
590
591 if (failCut(nOther >= m_minOtherHits, "track cut: minOtherHits")) {
592 continue;
593 }
594
595 ATH_MSG_DEBUG("Use TRT phase " << m_useTRTPhase << " is cosmic? " << m_isCosmic << " timecor " << timecor);
596 if (m_useTRTPhase or m_isCosmic) {
597 if (timecor == 0) {
598 continue;
599 }
600 static const double tmin{-15.};
601 static const double tmax{10.};
602 if (failCut((timecor >= tmin) and (timecor <= tmax), "track cut: timing cut")) {
603 continue;
604 }
605 ATH_MSG_DEBUG(timecor << " " << tmin << " " << tmax);
606 }
607
608 bool enclosingHits{true};
609 if (m_isCosmic) {
610 if (tsos->trackParameters()) {
611 zpos = tsos->trackParameters()->position().z();
612 enclosingHits = ((zpos > zmin) and (zpos < zmax));
613 } else {
614 ATH_MSG_WARNING("No track parameters found. Cannot determine whether it is an enclosed hit.");
615 enclosingHits = false;
616 }
617 } else {
618 layerSide = (m_sctId->barrel_ec(surfaceID) != 0) * N_BARRELS
619 + static_cast<float>(m_sctId->layer_disk(surfaceID))
620 + (static_cast<float>(m_sctId->side(surfaceID)) == 0) * 0.5;
621 enclosingHits = ((layerSide > min_layerSide) and (layerSide < max_layerSide));
622 }
623
625 (not (layerPlusHalfSide == 0.5)) and
626 (not ((isub == 1) and (layerPlusHalfSide == 3))) and
627 (not (layerPlusHalfSide == 8))) {
628 if (failCut(enclosingHits, "hit cut: enclosing hits")) {
629 continue;
630 }
631 }
632
633 // Now fill with the local z
634 double chi2{trackWithHoles->fitQuality()->chiSquared()};
635 int ndf{trackWithHoles->fitQuality()->numberDoF()};
636 double chi2_div_ndf{ndf > 0. ? chi2 / ndf : -1.};
637
638 if (failCut(std::abs(phiUp) <= m_maxPhiAngle, "hit cut: incidence angle")) {
639 continue;
640 }
641
642 if (failCut((ndf > 0) and (chi2_div_ndf <= m_maxChi2), "track cut: chi2 cut")) {
643 continue;
644 }
645
646 if (m_requireOtherFace and failCut(otherFaceFound, "hit cut: other face found")) {
647 continue;
648 }
649
650 if (not trkParamOnSurface) continue;
651 double xl{trkParamOnSurface->localPosition()[0]};
652 double yl{trkParamOnSurface->localPosition()[1]};
653
654 // Check guard ring
655 bool insideGuardRing{true};
656 if (isub == BARREL_INDEX) {
657 const float xGuard{m_effdistcut};
658 static const float yGuard{3.};
659 if (xl < -30.7 + xGuard) {
660 insideGuardRing = false;
661 }
662 if (xl > 30.7 - xGuard) {
663 insideGuardRing = false;
664 }
665
666 static const double yend{63.960 + 0.03 - 1.}; // The far sensitive end
667 static const double ydead{2.06 / 2.}; // the near sensitive end
668 if (yl > yend - yGuard) {
669 insideGuardRing = false;
670 }
671 if (yl < -yend + yGuard) {
672 insideGuardRing = false;
673 }
674 if ((yl < ydead + yGuard) and (yl > -ydead - yGuard)) {
675 insideGuardRing = false;
676 }
677 } else {
678 // No guard ring for the endcaps for now...just set true.
679 insideGuardRing = true;
680 }
681
682 if (m_requireGuardRing and failCut(insideGuardRing, "hit cut: inside guard ring")) {
683 continue;
684 }
685
686 // Check bad chips
687 if (m_vetoBadChips) {
688 bool nearBadChip{false};
689 IdentifierHash waferHash{m_sctId->wafer_hash(surfaceID)};
690 const InDetDD::SiDetectorElement* pElement{elements->getDetectorElement(waferHash)};
691 bool swap{(pElement->swapPhiReadoutDirection()) ? true : false};
692 int chipPos{previousChip(xl, side, swap)};
693 unsigned int status{0};
694 std::map<Identifier, unsigned int>::const_iterator badChip{badChips->find(module_id)};
695 if (badChip != badChips->end()) {
696 status = (*badChip).second;
697 // Veto if either of closest two chips is dead
698 const bool nearBadChipDead{(status & (1 << chipPos)) != 0};
699 const bool nextBadChipDead{(status & (1 << (chipPos + 1))) != 0};
700 const bool isNotEndChip{(chipPos != 5) and (chipPos != 11)}; // cant have a 'next' if its the end chip on that
701 // side
702 // nearBadChip = status & (1 << chipPos) or
703 // (chipPos != 5 and chipPos != 11 and status & (1 << (chipPos + 1)));
704 // clarify logic:
705 nearBadChip = nearBadChipDead or (isNotEndChip and nextBadChipDead);
706 }
707 if (failCut(not nearBadChip, "hit cut: not near bad chip")) {
708 continue;
709 }
710 }
711 ATH_MSG_VERBOSE("Candidate passed all cuts");
712
713 const int ieta{m_sctId->eta_module(surfaceID)};
714 const int iphi{m_sctId->phi_module(surfaceID)};
715
716 auto effAcc{Monitored::Scalar<float>("eff", eff)};
717 auto ineffAcc{Monitored::Scalar<float>("ineff", (testOffline ? 1. : 1.-eff))};
718 auto ietaAcc{Monitored::Scalar<int>("ieta"+etaPhiSuffix, ieta)};
719 auto iphiAcc{Monitored::Scalar<int>("iphi"+etaPhiSuffix, iphi)};
720 auto layerAcc{Monitored::Scalar<float>("layerPlusHalfSide", dedicated_layerPlusHalfSide)};
721 auto lumiAcc{Monitored::Scalar<int>("LumiBlock", ctx.eventID().lumi_block())};
722 auto isubAcc{Monitored::Scalar<int>("isub", isub)};
723 auto sideHashAcc{Monitored::Scalar<int>("sideHash", sideHash)};
724 auto isFirstBCIDAcc{Monitored::Scalar<bool>("isFirstBCID", (BCIDpos <= 0))};
725
726 //fill the histograms
727 fill(regionNames[isub].data(), effAcc, ineffAcc, ietaAcc, iphiAcc, layerAcc, lumiAcc, isFirstBCIDAcc);
728 fill("SCTHitEffMonitor", effAcc, lumiAcc, isubAcc, sideHashAcc, isFirstBCIDAcc);
729
730 if (testOffline) {
731 ATH_MSG_INFO("Filling " << detIndex << ", " << side << " eta " << ieta << " phi " << iphi);
732 }
733 } // End of loop over hits/holes
734 }
735 ATH_MSG_VERBOSE("finished loop over tracks = " << tracks->size());
736
737 return StatusCode::SUCCESS;
738}
739
#define M_PI
Scalar phi() const
phi method
Scalar theta() const
theta method
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_FATAL(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_VERBOSE(x)
#define ATH_MSG_WARNING(x)
#define ATH_MSG_DEBUG(x)
Helpers for checking error return status codes and reporting errors.
void swap(DataVector< T > &a, DataVector< T > &b)
See DataVector<T, BASE>::swap().
#define AmgVector(rows)
char data[hepevt_bytes_allocation_ATLAS]
Definition HepEvt.cxx:11
interface file for service that keeps track of configuration conditions
Header containing the InDetHierarchy enum, to avoid pulling in a class every time it is needed and na...
This is an Identifier helper class for the Pixel subdetector.
This is an Identifier helper class for the SCT subdetector.
Contains string formatting utility functions for use in SCT_Monitoring @ author shaun roe.
Handle class for reading from StoreGate.
This is an Identifier helper class for the TRT subdetector.
const ServiceHandle< StoreGateSvc > & detStore() const
Environment_t environment() const
Accessor functions for the environment.
virtual StatusCode initialize() override
initialize
AthMonitorAlgorithm(const std::string &name, ISvcLocator *pSvcLocator)
Constructor.
void getInitializedCache(MagField::AtlasFieldCache &cache) const
get B field cache for evaluation as a function of 2-d or 3-d position.
int distanceFromFront(const bcid_type bcid, const BunchDistanceType type=NanoSec) const
The distance of the specific bunch crossing from the front of the train.
@ BunchCrossings
Distance in units of 25 nanoseconds.
This class saves the "context" of an expanded identifier (ExpandedIdentifier) for compact or hash ver...
Definition IdContext.h:26
This is a "hash" representation of an Identifier.
bool is_valid() const
Check if id is in a valid state.
Class to hold the SiDetectorElement objects to be put in the detector store.
const SiDetectorElement * getDetectorElement(const IdentifierHash &hash) const
Class to hold geometrical description of a silicon detector element.
bool swapPhiReadoutDirection() const
Determine if readout direction between online and offline needs swapping.
virtual const Amg::Vector3D & normal() const override final
Get reconstruction local normal axes in global frame.
Local cache for magnetic field (based on MagFieldServices/AtlasFieldSvcTLS.h)
bool solenoidOn() const
status of the magnets
Declare a monitored scalar variable.
FloatProperty m_maxPhiAngle
IntegerProperty m_minTRTHits
FloatProperty m_maxChi2
SG::ReadHandleKey< TrackCollection > m_TrackName
BooleanProperty m_vetoBadChips
const SCT_ID * m_sctId
SCTHitEffMonAlg(const std::string &name, ISvcLocator *pSvcLocator)
int becIdxLayer2Index(const int becIdx, const int layer) const
ToolHandle< Trk::ITrackHoleSearchTool > m_holeSearchTool
UnsignedIntegerProperty m_maxSiHoles
BooleanProperty m_useIDGlobal
int getWaferIndex(const int barrel_bc, const int layer_disk, const int side) const
const TRT_ID * m_trtId
SG::ReadCondHandleKey< BunchCrossingCondData > m_bunchCrossingKey
FloatProperty m_effdistcut
BooleanProperty m_insideOutOnly
IntegerProperty m_minOtherHits
const PixelID * m_pixelId
virtual StatusCode fillHistograms(const EventContext &ctx) const override final
adds event to the monitoring histograms
std::string m_path
SG::ReadCondHandleKey< AtlasFieldCacheCondObj > m_fieldCondObjInputKey
FloatProperty m_maxD0
UnsignedIntegerProperty m_maxTracks
SG::ReadHandleKey< ComTime > m_comTimeName
BooleanProperty m_requireOtherFace
BooleanProperty m_requireGuardRing
int previousChip(double xl, int side, bool swap) const
SG::ReadHandleKey< InDet::SCT_ClusterContainer > m_sctContainerName
IntegerProperty m_minPixelHits
ToolHandle< Trk::IResidualPullCalculator > m_residualPullCalculator
ToolHandle< ISCT_ConfigurationConditionsTool > m_configConditions
ToolHandle< Trk::IRIO_OnTrackCreator > m_rotcreator
IntegerProperty m_minSCTHits
double getResidual(const Identifier &surfaceID, const Trk::TrackParameters *trkParam, const InDet::SCT_ClusterContainer *p_sctclcontainer) const
StatusCode findAnglesToWaferSurface(const Amg::Vector3D &mom, const Identifier id, const InDetDD::SiDetectorElementCollection *elements, double &theta, double &phi) const
BooleanProperty m_useSCTorTRT
BooleanProperty m_requireEnclosingHits
UnsignedIntegerProperty m_minSiHits
BooleanProperty m_useTRTPhase
FloatProperty m_minPt
virtual StatusCode initialize() override final
initialize
SG::ReadCondHandleKey< InDetDD::SiDetectorElementCollection > m_SCTDetEleCollKey
FloatProperty m_maxZ0sinTheta
BooleanProperty m_isCosmic
StatusCode failCut(bool value, const std::string &name) const
const_pointer_type retrieve()
virtual bool isValid() override final
Can the handle be successfully dereferenced?
This class is the pure abstract base class for all fittable tracking measurements.
virtual const Surface & associatedSurface() const =0
Interface method to get the associated Surface.
const Amg::Vector3D & momentum() const
Access method for the momentum.
double pT() const
Access method for transverse momentum.
Amg::Vector2D localPosition() const
Access method for the local coordinates, local parameter definitions differ for each surface type.
@ Unbiased
RP with track state that has measurement not included.
const TrkDetElementBase * associatedDetectorElement() const
return associated Detector Element
@ SiSPSeededFinder
Tracks from SiSPSeedFinder.
represents the track state (measurement, material, fit parameters and quality) at a surface.
@ Measurement
This is a measurement, and will at least contain a Trk::MeasurementBase.
@ Outlier
This TSoS contains an outlier, that is, it contains a MeasurementBase/RIO_OnTrack which was not used ...
@ Hole
A hole on the track - this is defined in the following way.
A summary of the information contained by a track.
virtual Identifier identify() const =0
Identifier.
double chi2(TH1 *h0, TH1 *h1)
Eigen::Matrix< double, 3, 1 > Vector3D
unsigned int bec2Index(const int becVal)
Conversion bec->index.
static const std::vector< int > n_layers
ParametersT< TrackParametersDim, Charged, PerigeeSurface > Perigee
@ theta
Definition ParamDefs.h:66
@ loc1
Definition ParamDefs.h:34
@ d0
Definition ParamDefs.h:63
@ z0
Definition ParamDefs.h:64
ParametersBase< TrackParametersDim, Charged > TrackParameters
void fill(H5::Group &out_file, size_t iterations)