ATLAS Offline Software
Loading...
Searching...
No Matches
SCT_FastDigitizationTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
6
7// Pile-up
9
10// Hit class includes
12#include "Identifier/Identifier.h"
14
15// Det Descr includes
17
22
23// FATRAS
25#include "TrkSurfaces/Surface.h"
33
35
36// Gaudi
37#include "GaudiKernel/SystemOfUnits.h"
38
41
42// CLHEP
44#include "CLHEP/Random/RandomEngine.h"
45#include "CLHEP/Random/RandGaussZiggurat.h"
46#include "CLHEP/Random/RandLandau.h"
47
48#include <algorithm>
49#include <cmath>
50#include <memory>
51#include <sstream>
52#include <string>
53
55 const std::string& name,
56 const IInterface* parent) :
57
58 PileUpToolBase(type, name, parent)
59{
60}
61
62//----------------------------------------------------------------------
63// Initialize method:
64//----------------------------------------------------------------------
66{
67
68 //locate the AtRndmGenSvc and initialize our local ptr
69 CHECK(m_rndmSvc.retrieve());
70
71 CHECK(detStore()->retrieve(m_sct_ID, "SCT_ID"));
72
73 if (m_inputObjectName=="")
74 {
75 ATH_MSG_FATAL ( "Property InputObjectName not set !" );
76 return StatusCode::FAILURE;
77 }
78 else
79 {
80 ATH_MSG_DEBUG ( "Input objects: '" << m_inputObjectName << "'" );
81 }
83 ATH_CHECK(m_sctPrdTruthKey.initialize());
84
85 // retrieve the offline cluster maker : for pixel and/or sct
86 if (!m_clusterMaker.empty())
87 {
88 CHECK(m_clusterMaker.retrieve());
89 }
90
91 //locate the PileUpMergeSvc and initialize our local ptr
92 CHECK(m_mergeSvc.retrieve());
93
94 CHECK(m_lorentzAngleTool.retrieve());
95 //Initialize threshold
96 m_sctMinimalPathCut = m_sctMinimalPathCut * Gaudi::Units::micrometer;
97
98 // Initialize ReadCondHandleKey
99 ATH_CHECK(m_SCTDetEleCollKey.initialize());
100
101 return StatusCode::SUCCESS ;
102}
103
104StatusCode SCT_FastDigitizationTool::prepareEvent(const EventContext& /*ctx*/, unsigned int)
105{
106
107 m_siHitCollList.clear();
110 return StatusCode::SUCCESS;
111
112}
113
115 SubEventIterator bSubEvents,
116 SubEventIterator eSubEvents)
117{
118 //decide if this event will be processed depending on HardScatterSplittingMode & bunchXing
119 if (m_HardScatterSplittingMode == 2 && !m_HardScatterSplittingSkipper ) { m_HardScatterSplittingSkipper = true; return StatusCode::SUCCESS; }
120 if (m_HardScatterSplittingMode == 1 && m_HardScatterSplittingSkipper ) { return StatusCode::SUCCESS; }
122
124 TimedHitCollList hitCollList;
125
126 if (!(m_mergeSvc->retrieveSubSetEvtData(m_inputObjectName.value(), hitCollList, bunchXing,
127 bSubEvents, eSubEvents).isSuccess()) &&
128 hitCollList.empty()) {
129 ATH_MSG_ERROR("Could not fill TimedHitCollList");
130 return StatusCode::FAILURE;
131 } else {
132 ATH_MSG_VERBOSE(hitCollList.size() << " SiHitCollections with key " <<
133 m_inputObjectName << " found");
134 }
135
136 TimedHitCollList::iterator iColl(hitCollList.begin());
137 TimedHitCollList::iterator endColl(hitCollList.end());
138
139 for( ; iColl != endColl; ++iColl) {
140 SiHitCollection *siHitColl = new SiHitCollection(*iColl->second);
141 PileUpTimeEventIndex timeIndex(iColl->first);
142 ATH_MSG_DEBUG("SiHitCollection found with " << siHitColl->size() <<
143 " hits");
144 ATH_MSG_VERBOSE("time index info. time: " << timeIndex.time()
145 << " index: " << timeIndex.index()
146 << " type: " << timeIndex.type());
147 m_thpcsi->insert(timeIndex, siHitColl);
148 m_siHitCollList.push_back(siHitColl);
149 }
150
151 return StatusCode::SUCCESS;
152}
153
154
155StatusCode SCT_FastDigitizationTool::processAllSubEvents(const EventContext& ctx) {
156
157 // get the container(s)
159
160 //this is a list<pair<time_t, DataLink<SCTUncompressedHitCollection> > >
161 TimedHitCollList hitCollList;
162 unsigned int numberOfSimHits(0);
163 if ( !(m_mergeSvc->retrieveSubEvtsData(m_inputObjectName.value(), hitCollList, numberOfSimHits).isSuccess()) && hitCollList.empty() )
164 {
165 ATH_MSG_ERROR ( "Could not fill TimedHitCollList" );
166 return StatusCode::FAILURE;
167 }
168 else
169 {
170 ATH_MSG_DEBUG ( hitCollList.size() << " SiHitCollections with key " << m_inputObjectName << " found" );
171 }
172
173 // Define Hit Collection
174 TimedHitCollection<SiHit> thpcsi(numberOfSimHits);
175
176 //now merge all collections into one
177 TimedHitCollList::iterator iColl(hitCollList.begin());
178 TimedHitCollList::iterator endColl(hitCollList.end() );
179
181 // loop on the hit collections
182 while ( iColl != endColl )
183 {
184 //decide if this event will be processed depending on HardScatterSplittingMode & bunchXing
186 if (m_HardScatterSplittingMode == 1 && m_HardScatterSplittingSkipper ) { ++iColl; continue; }
188 const SiHitCollection* p_collection(iColl->second);
189 thpcsi.insert(iColl->first, p_collection);
190 ATH_MSG_DEBUG ( "SiHitCollection found with " << p_collection->size() << " hits" );
191 ++iColl;
192 }
193
194 // Process the Hits
195 CHECK(this->digitize(ctx, thpcsi));
196
197 CHECK(this->createAndStoreRIOs(ctx));
198 ATH_MSG_DEBUG ( "createAndStoreRIOs() succeeded" );
199
200 return StatusCode::SUCCESS;
201}
202
203
204
205StatusCode SCT_FastDigitizationTool::mergeEvent(const EventContext& ctx)
206{
207 if (m_thpcsi != nullptr)
208 {
209 CHECK(this->digitize(ctx, *m_thpcsi));
210 }
211
212 //-----------------------------------------------------------------------
213 // Clean up temporary containers
214 delete m_thpcsi;
215 for(SiHitCollection* ptr : m_siHitCollList) delete ptr;
216 m_siHitCollList.clear();
217 //-----------------------------------------------------------------------
218
219 CHECK(this->createAndStoreRIOs(ctx));
220 ATH_MSG_DEBUG ( "createAndStoreRIOs() succeeded" );
221
222 return StatusCode::SUCCESS;
223}
224
225
226StatusCode SCT_FastDigitizationTool::digitize(const EventContext& ctx,
228{
229 // truth info
231 sctPrdTruth = std::make_unique< PRD_MultiTruthCollection >();
232 if ( !sctPrdTruth.isValid() ) {
233 ATH_MSG_FATAL( "Could not record collection " << sctPrdTruth.name() );
234 return StatusCode::FAILURE;
235 }
236 ATH_MSG_DEBUG( "PRD_MultiTruthCollection " << sctPrdTruth.name() << " registered in StoreGate" );
237
238 // Set the RNG to use for this event.
239 ATHRNG::RNGWrapper* rngWrapper = m_rndmSvc->getEngine(this, m_randomEngineName);
240 const std::string rngName = name()+m_randomEngineName;
241 rngWrapper->setSeed( rngName, ctx );
242 CLHEP::HepRandomEngine *rndmEngine = rngWrapper->getEngine(ctx);
243
244 // Get SCT_DetectorElementCollection
246 const InDetDD::SiDetectorElementCollection* elements(sctDetEle.retrieve());
247 if (elements==nullptr) {
248 ATH_MSG_FATAL(m_SCTDetEleCollKey.fullKey() << " could not be retrieved");
249 return StatusCode::FAILURE;
250 }
251
254 else { m_sctClusterMap->clear(); }
255 while (thpcsi.nextDetectorElement(i, e))
256 {
257 SCT_detElement_RIO_map SCT_DetElClusterMap;
258 std::vector<int> truthIdList;
259 std::vector<Identifier> detEl;
260 while (i != e)
261 {
262 const TimedHitPtr<SiHit>& currentSiHit(*i++);
263 // check the status of truth information for this SiHit
264 // some Truth information is cut for pile up events
265 const HepMcParticleLink currentLink = HepMcParticleLink::getRedirectedLink(currentSiHit->particleLink(), currentSiHit.eventId(), ctx); // This link should now correctly resolve to the TruthEvent McEventCollection in the main StoreGateSvc.
266
267 const Identifier waferId = m_sct_ID->wafer_id(currentSiHit->getBarrelEndcap(), currentSiHit->getLayerDisk(), currentSiHit->getPhiModule(), currentSiHit->getEtaModule(), currentSiHit->getSide());
268 const IdentifierHash waferHash = m_sct_ID->wafer_hash(waferId);
269 const InDetDD::SiDetectorElement *hitSiDetElement = elements->getDetectorElement(waferHash);
270 if (!hitSiDetElement)
271 {
272 ATH_MSG_ERROR( "Could not get detector element.");
273 continue;
274 }
275
276 // the module design
277 const InDetDD::SCT_ModuleSideDesign* design = dynamic_cast<const InDetDD::SCT_ModuleSideDesign*>(&hitSiDetElement->design());
278 if (!design)
279 {
280 ATH_MSG_WARNING ( "SCT_DetailedSurfaceChargesGenerator::process can not get "<< design) ;
281 continue;
282 }
283
284 std::vector<HepMcParticleLink> hit_vector; //Store the hits in merged cluster
285
286 // Process only one hit by the same particle in the same detector element
287 bool isRep = false;
288 const int truthID = (currentLink.barcode() !=0 && currentLink.id() == 0) ? 3 : currentLink.id(); // FIXME barcode-based Patch for reading in legacy barcode-based EDM - if the barcode is non-zero, but the id is zero then we must be looking at a particle linked to suppressed pile-up truth - such SiHits would be linked to the third GenParticle in their GenEvents (if they were present)
289 const Identifier detElId = hitSiDetElement->identify();
290 for (int j : truthIdList)
291 {
292 for (auto & k : detEl)
293 {
294 if ((truthID > 0) && (truthID == j) && (detElId == k)) {isRep = true; break;}
295 }
296 if (isRep) { break; }
297 }
298 if (isRep) { continue; }
299 truthIdList.push_back(truthID);
300 detEl.push_back(detElId);
301
302 const double hitDepth = hitSiDetElement->hitDepthDirection();
303
304 double shiftX,shiftY;
305 if (hitSiDetElement->isBarrel()){
308 }
309 else{
312 }
313
314 HepGeom::Point3D<double> localStartPosition = hitSiDetElement->hitLocalToLocal3D(currentSiHit->localStartPosition());
315 HepGeom::Point3D<double> localEndPosition = hitSiDetElement->hitLocalToLocal3D(currentSiHit->localEndPosition());
316
317 Diffuse(localStartPosition,localEndPosition, shiftX * Gaudi::Units::micrometer, shiftY * Gaudi::Units::micrometer);
318
319 const double localEntryX = localStartPosition.x();
320 const double localEntryY = localStartPosition.y();
321 const double localEntryZ = localStartPosition.z();
322 const double localExitX = localEndPosition.x();
323 const double localExitY = localEndPosition.y();
324 const double localExitZ = localEndPosition.z();
325
326
327
328 const Amg::Vector2D localEntry(localEntryX,localEntryY);
329 const Amg::Vector2D localExit(localExitX,localExitY);
330 const Amg::Vector3D localExit3D(localExitX,localExitY,localExitZ);
331
332 const double thickness = hitSiDetElement->thickness();
333
334 const Trk::Surface *hitSurface = &hitSiDetElement->surface();
335
336 const double distX = localExitX-localEntryX;
337 const double distY = localExitY-localEntryY;
338 const double distZ = localExitZ-localEntryZ;
339
340 const Amg::Vector3D localDirection(distX, distY, distZ);
341 // path length statistics
342 double potentialClusterPath_Geom = localDirection.mag(); // geometrical path length
343 double potentialClusterPath_Step = 0.; // path calculated through stepping
344 double potentialClusterPath_Used = 0.; // path used (contains smearing & cut if applied)
345
346 // relational slope
347 const double slopeYX = distY/distX;
348 const double slopeXZ = distX/distZ;
349 const double slopeZX = distZ/distX;
350 // signs of stepping
351 const int signX = distX > 0. ? 1 : -1 ;
352 const int signY = distY > 0. ? 1 : -1 ;
353 const int signZ = distZ > 0. ? 1 : -1 ;
354
355 // get the identifier of the entry and the exit
356 const Identifier entryId = hitSiDetElement->identifierOfPosition(localEntry);
357 const Identifier exitId = hitSiDetElement->identifierOfPosition(localExit);
358 // now get the cellIds and check whether they're valid
359 const InDetDD::SiCellId entryCellId = hitSiDetElement->cellIdFromIdentifier(entryId);
360 const InDetDD::SiCellId exitCellId = hitSiDetElement->cellIdFromIdentifier(exitId);
361 // entry / exit validity
362 const bool entryValid = entryCellId.isValid();
363 const bool exitValid = exitCellId.isValid();
364
365 // the intersecetion id and cellId of it
366 const double par = -localEntryZ/(localExitZ-localEntryZ);
367 const double interX = localEntryX + par*(localExitX-localEntryX);
368 const double interY = localEntryY + par*(localExitY-localEntryY);
369
370 const Amg::Vector2D intersection(interX,interY);
371 const Identifier intersectionId = hitSiDetElement->identifierOfPosition(intersection);
372
373 // apply the lorentz correction
374 const IdentifierHash detElHash = hitSiDetElement->identifyHash();
375 const double tanLorAng = m_sctTanLorentzAngleScalor*m_lorentzAngleTool->getTanLorentzAngle(detElHash, ctx);
376 const int lorentzDirection = tanLorAng > 0. ? 1 : -1;
377 const bool useLorentzDrift = std::abs(tanLorAng) > 0.01;
378 // shift parameters
379 const double shift = m_lorentzAngleTool->getLorentzShift(detElHash, ctx);
380 // lorenz angle effects : offset goes against the lorentzAngle
381 const double xLoffset = -lorentzDirection*thickness*tanLorAng;
382
383 // --------------------------------------------------------------------------------------
384 // fast exit: skip non-valid entry && exit
385 if (!entryValid && !exitValid)
386 {
387 continue;
388 }
389
390 std::vector<Identifier> potentialClusterRDOList;
391 std::map<Identifier, double> surfaceChargeWeights;
392 // min/max indices
393 int phiIndexMinRaw = 1000;
394 int phiIndexMaxRaw = -1000;
395
396 // is it a single strip w/o drift effect ? - also check the numerical stability
397 const bool singleStrip = (entryCellId == exitCellId && entryValid);
398 if (singleStrip && !useLorentzDrift)
399 {
400 // ----------------------- single strip lucky case ----------------------------------------
401 // 1 strip cluster without drift effect
402 surfaceChargeWeights[intersectionId] = potentialClusterPath_Geom;
403 }
404 else
405 {
406 // the start parameters
407 int strips = 0;
408 // needed for both approaches with and w/o drift
409 Identifier currentId = entryId;
410 InDetDD::SiCellId currentCellId = entryCellId;
411 Amg::Vector2D currentCenterPosition = hitSiDetElement->rawLocalPositionOfCell(currentCellId);
412 Amg::Vector3D currentPosition3D(localEntryX,localEntryY,localEntryZ);
413 Amg::Vector3D currentStep3D(0.,0.,0.);
414
415 // ============================== the clusteristiaon core =====================================================
416 // ----------------------- barrel geometrical clustering with drift -------------------------------------------
417 // there are two independent loops
418 // (a) the geometrical steps through the strips : labelled current
419 Amg::Vector2D currentCenterStep(0.,0.);
420 // check for non-valid entry diode ... this needs to be reset then
421 // ---------------------------------------------------
422 // start position needs to be reset : --------
423 if (!entryValid)
424 {
425 // the number of strips in Phi
426 const int numberOfDiodesPhi = design->cells();
427 // the simple case is if the exit is outside locY
428 if (!hitSurface->bounds().insideLoc2(localEntry))
429 {
430 // step towards the border
431 const double stepInY = signY*(std::abs(localEntryY)-0.5*hitSiDetElement->length());
432 const double stepInX = stepInY*distX/distY;
433 const double stepInZ = stepInY*distZ/distY;
434 currentStep3D = Amg::Vector3D(stepInX,stepInY,stepInZ);
435 }
436 else
437 {
438 //get the last valid phi border
439 const int phiExitIndex = exitCellId.phiIndex() <= 2 ? 0 : numberOfDiodesPhi-1;
440
441 const InDetDD::SiCellId phiExitId(phiExitIndex);
442 const Amg::Vector2D phiExitCenter = hitSiDetElement->rawLocalPositionOfCell(phiExitId);
443 // fill the step parameters
444 // this may need to be changed to Rectangular/Trapezoid check
445 currentStep3D = stepToStripBorder(*hitSiDetElement,
446 //*hitSurface,
447 localEntryX, localEntryY,
448 localExitX, localExitY,
449 slopeYX,
450 slopeZX,
451 phiExitCenter,
452 signX);
453 } // ENDIF !hitSurface->bounds().insideLoc2(localEntry)
454
455 // get to the first valid strip ---------------------------------------------------
456 currentPosition3D += currentStep3D;
457 // for the record
458 potentialClusterPath_Step += currentStep3D.mag();
459 ATH_MSG_VERBOSE("[ cluster - sct ] Strip entry shifted by " << currentStep3D << " ( " << potentialClusterPath_Step << " )");
460 // for step epsilon into the first valid
461 const Amg::Vector2D positionInFirstValid(currentPosition3D.x()+0.01*signX,currentPosition3D.y()+0.01*signY);
462 // reset the entry parameters to the first valid pixel
463 currentId = hitSiDetElement->identifierOfPosition(positionInFirstValid);
464 currentCellId = hitSiDetElement->cellIdFromIdentifier(currentId);
465 currentCenterPosition = hitSiDetElement->rawLocalPositionOfCell(currentId);
466
467 } // ----- start position has been reset -------- ( // endif (!entryValid) )
468
469 // (b) the collection of strips due to surface charge
470 // the lorentz plane setp
471 double lplaneStepX = 0.;
472 double lplaneStepY = 0.;
473 Amg::Vector3D lplaneIntersection(0.,0.,0.);
474 Amg::Vector3D driftPrePosition3D(currentPosition3D);
475 Amg::Vector3D driftPostPosition3D(currentPosition3D);
476 // (c) simple cache for the purely geometrical clustering
477 Identifier lastId = currentId;
478 bool lastStrip = false;
479 ATH_MSG_VERBOSE("[ cluster - sct ] CurrentPosition " << currentPosition3D );
480
481 // the steps between the strips -------------------------------------------
482 for ( ; ; ++strips)
483 {
484 // -------------------------------------------------------------------------------------------------
485 // current phi/eta indices
486 const int currentPhiIndex = currentCellId.phiIndex();
487 // record for the full validation
488 // (a) steps through the strips
489 // sct break for last strip or if you step out of the game
490 if (lastStrip || currentPosition3D.z() > 0.5*thickness || strips > 4)
491 {
492 break;
493 }
494 // no single valid strip
495 if (!exitValid && !currentCellId.isValid())
496 {
497 break;
498 }
499 // cache it
500 phiIndexMinRaw = currentPhiIndex < phiIndexMinRaw ? currentPhiIndex : phiIndexMinRaw;
501 phiIndexMaxRaw = currentPhiIndex > phiIndexMaxRaw ? currentPhiIndex : phiIndexMaxRaw;
502 // find out if this is the last step
503 lastStrip = (currentPhiIndex == exitCellId.phiIndex());
504 // get the current Pitch
505 const double currentPitchX = hitSiDetElement->phiPitch(currentCenterPosition);
506 // the next & previous sct borders are needed (next is w.r.t to the track direction)
507 std::vector<double> lorentzLinePositions;
508 const int trackDir = slopeXZ > 0 ? 1 : -1; //FIXME will be multiplying doubles by this int!
509 lorentzLinePositions.reserve(2);
510 // the both pixel borders left/right
511 lorentzLinePositions.push_back(currentCenterPosition.x() + trackDir*0.5*currentPitchX);
512 lorentzLinePositions.push_back(currentCenterPosition.x() - trackDir*0.5*currentPitchX);
513 // the third line is possible -> it is due to xOffset > pitchX
514 if (xLoffset*xLoffset > currentPitchX*currentPitchX)
515 {
516 lorentzLinePositions.push_back(currentCenterPosition.x() + lorentzDirection*1.5*currentPitchX);
517 }
518 // intersect the effective lorentz plane if the intersection is not valid anymore
519 bool lplaneInterInCurrent(false);
520 double lorentzPlaneHalfX(0.);
521 Amg::Vector3D lplaneCandidate(0.,0.,0.);
522 std::vector<double>::iterator lorentzLinePosIter = lorentzLinePositions.begin();
523 // find the intersection solutions for the three cases
524 int lplaneDirection = 100; // solve the intersection case first
525 // test left and right lorentz planes of this pixel
526 for ( ; lorentzLinePosIter != lorentzLinePositions.end(); ++lorentzLinePosIter)
527 {
528 // first - do the intersection : the readout side is respected by the hit depth direction
529 Trk::LineIntersection2D intersectLorentzPlane(localEntryX,-0.5*signZ*thickness,localExitX,0.5*signZ*thickness,
530 (*lorentzLinePosIter)+xLoffset,-0.5*hitDepth*thickness,
531 (*lorentzLinePosIter),0.5*hitDepth*thickness);
532 // avoid repeating intersections
533 const double formerPlaneStepZ = intersectLorentzPlane.interY-lplaneIntersection.z();
534 if (formerPlaneStepZ*formerPlaneStepZ < 10e-5)
535 {
536 lplaneInterInCurrent = false;
537 continue;
538 }
539 // is the intersection within the z thickness ?
540 lplaneInterInCurrent = intersectLorentzPlane.interY > -0.5*thickness
541 && intersectLorentzPlane.interY < 0.5*thickness;
542 // the step in z from the former plane intersection
543 // only go on if it is worth it
544 // (a) it has to be within z boundaries
545 if (lplaneInterInCurrent)
546 {
547 // record: the half position of the loretnz plane - for estimation to be under/over
548 lorentzPlaneHalfX = (*lorentzLinePosIter)+0.5*xLoffset;
549 // plane step parameters
550 lplaneStepX = intersectLorentzPlane.interX-localEntryX;
551 lplaneStepY = lplaneStepX*slopeYX;
552 // todo -> break condition if you are hitting the same intersection
553 lplaneCandidate = Amg::Vector3D(intersectLorentzPlane.interX,
554 localEntryY+lplaneStepY,
555 intersectLorentzPlane.interY);
556 // check in y, the x direction is only needed to find out the drift direction
557 const double distToNextLineY = 0.5*hitSiDetElement->length()-lplaneCandidate.y();
558 const double distToPrevLineY = -0.5*hitSiDetElement->length()-lplaneCandidate.y();
559 lplaneInterInCurrent = (distToNextLineY*distToPrevLineY) < 0.;
560 // we have an intersection candidate - needs to be resolved for +1/-1
561 lplaneDirection = lplaneInterInCurrent ? 0 : lplaneDirection;
562 if (lplaneInterInCurrent) {break;}
563 }
564 }
565 // now assign it (if valid)
566 if (lplaneInterInCurrent) {lplaneIntersection = lplaneCandidate;}
567 ATH_MSG_VERBOSE( "[ cluster - pix ] Lorentz plane intersection x/y/z = "
568 << lplaneCandidate.x() << ", "
569 << lplaneCandidate.y() << ", "
570 << lplaneCandidate.z() );
571
572 // now solve for 1 / -1 if needed
573 if (lplaneDirection)
574 {
575 // check the z position of the track at this stage
576 const double trackZatlplaneHalfX = (lorentzPlaneHalfX-localEntryX)*slopeXZ - 0.5*thickness;
577 lplaneDirection = trackZatlplaneHalfX < 0. ? -1 : 1;
578 }
579
580 // record the lorentz plane intersections
581 // calculate the potential step in X and Y
582 currentStep3D = lastStrip ? localExit3D-currentPosition3D :
583 stepToStripBorder(*hitSiDetElement,
584 //*hitSurface,
585 currentPosition3D.x(), currentPosition3D.y(),
586 localExitX, localExitY,
587 slopeYX,
588 slopeZX,
589 currentCenterPosition,
590 signX);
591
592 // add the current Step to the current position
593 currentPosition3D += currentStep3D;
594 // check whether the step has led outside
595 if (!hitSurface->bounds().insideLoc2(Amg::Vector2D(currentPosition3D.x(),
596 currentPosition3D.y())))
597 { // stepping outside in y calls for last step
598 lastStrip = true;
599 // correct to the new position
600 currentPosition3D -= currentStep3D;
601 const double stepInY = signY*0.5*hitSiDetElement->length()-currentPosition3D.y();
602 const double stepInX = distX/distY*stepInY;
603 const double stepInZ = slopeZX*stepInX;
604 // update to the new currentStep
605 currentStep3D = Amg::Vector3D(stepInX,stepInY,stepInZ);
606 currentPosition3D += currentStep3D;
607 }
608 // if (currentPosition3D.z() > 0.501*signZ*thickness){
609 if (std::abs(currentPosition3D.z()) > 0.501*thickness)
610 {
611 // step has led out of the silicon, correct for it
612 lastStrip = true;
613 // correct to the new position (has been seen only three times ... probably numerical problem)
614 currentPosition3D -= currentStep3D;
615 currentStep3D = localExit3D-currentPosition3D;
616 currentPosition3D = localExit3D;
617 //
618 ATH_MSG_VERBOSE("[ cluster - sct ] - current position set to local Exit position !");
619 }
620
621 // update the current values for the next step
622 const Amg::Vector2D currentInsidePosition(currentPosition3D.x()+0.01*signX,currentPosition3D.y()+0.01*signY);
623 currentId = hitSiDetElement->identifierOfPosition(currentInsidePosition);
624 currentCellId = hitSiDetElement->cellIdFromIdentifier(currentId);
625 // just to be sure also for fan structure cases
626 currentCenterPosition = hitSiDetElement->rawLocalPositionOfCell(currentCellId);
627 // The new current Position && the path length for monitoring
628 potentialClusterPath_Step += currentStep3D.mag();
629 ATH_MSG_VERBOSE("[ cluster - sct ] CurrentPosition " << currentPosition3D
630 << " ( yielded by :" << currentStep3D << ")");
631 // setting the drift Post position
632 driftPostPosition3D = lplaneInterInCurrent ? lplaneIntersection : currentPosition3D;
633 // ---------- the surface charge is emulated -------------------------------------------------------
634 if (m_sctEmulateSurfaceCharge && useLorentzDrift)
635 {
636 // loop to catch lpintersection in last step
637 const int currentDrifts = (lastStrip && lplaneInterInCurrent) ? 2 : 1;
638 for (int idrift = 0; idrift < currentDrifts; ++idrift)
639 {
640 // const assignment for fast access, take intersection solution first, then cell exit
641 const Amg::Vector3D& currentDriftPrePosition = idrift ? driftPostPosition3D : driftPrePosition3D;
642 const Amg::Vector3D& currentDriftPostPosition = idrift ? localExit3D : driftPostPosition3D;
643 // get the center of the step and drift it to the surface
644 const Amg::Vector3D driftStepCenter = 0.5*(currentDriftPrePosition+currentDriftPostPosition);
645 // respect the reaout side through the hit dept direction
646 const double driftZtoSurface = 0.5*hitDepth*thickness-driftStepCenter.z();
647 // record the drift position on the surface
648 const double driftPositionAtSurfaceX = driftStepCenter.x() + tanLorAng*driftZtoSurface;
649 const Amg::Vector2D driftAtSurface(driftPositionAtSurfaceX,
650 driftStepCenter.y());
651 const Identifier surfaceChargeId = hitSiDetElement->identifierOfPosition(driftAtSurface);
652 if (surfaceChargeId.is_valid())
653 {
654 // check if the pixel has already got some charge
655 if (surfaceChargeWeights.find(surfaceChargeId) == surfaceChargeWeights.end())
656 {
657 surfaceChargeWeights[surfaceChargeId] = (currentDriftPostPosition-currentDriftPrePosition).mag();
658 }
659 else
660 {
661 surfaceChargeWeights[surfaceChargeId] += (currentDriftPostPosition-currentDriftPrePosition).mag();
662 }
663 }
664 // record the drift step for validation
665 } // end of last step intersection check
666 }
667 else // ---------- purely geometrical clustering w/o surface charge ---------------------------
668 {
669 surfaceChargeWeights[lastId] = currentStep3D.mag();
670 }
671 // next pre is current post && lastId is currentId
672 driftPrePosition3D = driftPostPosition3D;
673 lastId = currentId;
674
675 } // end of steps between strips ----------------------------------------------------------------------
676 }
677
678 // the calculated local position
679 double totalWeight = 0.;
680 Amg::Vector2D potentialClusterPosition(0.,0.);
681 std::map<Identifier,double>::iterator weightIter = surfaceChargeWeights.begin();
682 for ( ; weightIter != surfaceChargeWeights.end(); ++weightIter)
683 {
684 // get the (effective) path length in the strip
685 double chargeWeight = (weightIter)->second;
686 const Identifier chargeId = (weightIter)->first;
687 // charge smearing if set : 2 possibilities landau/gauss
688 // two options fro charge smearing: landau / gauss
689 if ( m_sctSmearPathLength > 0. )
690 {
691 // create the smdar parameter
692 const double sPar = m_sctSmearLandau ?
693 m_sctSmearPathLength*CLHEP::RandLandau::shoot(rndmEngine) :
694 m_sctSmearPathLength*CLHEP::RandGaussZiggurat::shoot(rndmEngine);
695 chargeWeight *= (1.+sPar);
696 }
697
698 // the threshold cut
699 if (!(chargeWeight > m_sctMinimalPathCut)) { continue; }
700
701 // get the position according to the identifier
702 const Amg::Vector2D chargeCenterPosition = hitSiDetElement->rawLocalPositionOfCell(chargeId);
703 potentialClusterPath_Used += chargeWeight;
704 // taken Weight (Fatras can do analog SCT clustering)
705 const double takenWeight = m_sctAnalogStripClustering ? chargeWeight : 1.;
706 totalWeight += takenWeight;
707 potentialClusterPosition += takenWeight * chargeCenterPosition;
708 // and record the rdo
709 potentialClusterRDOList.push_back(chargeId);
710 }
711 // bail out - no left overs after cut
712
713 if (potentialClusterRDOList.empty() || potentialClusterPath_Used < m_sctMinimalPathCut)
714 {
715 continue;
716 }
717
718
719
720 // ---------------------------------------------------------------------------------------------
721 // PART 2: Cluster && ROT creation
722 //
723 // the Cluster Parameters -----------------------------
724 // normalize cluster position && get identifier
725 if (totalWeight == 0.)[[unlikely]]{
726 ATH_MSG_WARNING("totalWeight is zero.");
727 continue;
728 }
729 potentialClusterPosition *= 1./totalWeight;
730 /*const */Identifier potentialClusterId = hitSiDetElement->identifierOfPosition(potentialClusterPosition);
731 if (!potentialClusterId.is_valid()) {continue;}
732
733 const IdentifierHash waferID = m_sct_ID->wafer_hash(hitSiDetElement->identify());
734
735 // merging clusters
736 if(m_mergeCluster){
737 unsigned int countC(0);
738 ATH_MSG_INFO("Before cluster merging there were " << SCT_DetElClusterMap.size() << " clusters in the SCT_DetElClusterMap.");
739 for(SCT_detElement_RIO_map::iterator existingClusterIter = SCT_DetElClusterMap.begin(); existingClusterIter != SCT_DetElClusterMap.end();)
740 {
741 ++countC;
742 if (countC>100)
743 {
744 ATH_MSG_WARNING("Over 100 clusters checked for merging - bailing out!!");
745 break;
746 }
747 if (m_sct_ID->wafer_hash(((existingClusterIter->second)->detectorElement())->identify()) != waferID) {continue;}
748 //make a temporary to use within the loop and possibly erase - increment the main interator at the same time.
749 SCT_detElement_RIO_map::iterator currentExistingClusterIter = existingClusterIter++;
750
751 const InDet::SCT_Cluster *existingCluster = (currentExistingClusterIter->second);
752 bool isNeighbour = this->NeighbouringClusters(potentialClusterRDOList, existingCluster);
753 if(isNeighbour)
754 {
755 //Merge the clusters
756 const std::vector<Identifier> &existingClusterRDOList = existingCluster->rdoList();
757 potentialClusterRDOList.insert(potentialClusterRDOList.end(), existingClusterRDOList.begin(), existingClusterRDOList.end() );
758 Amg::Vector2D existingClusterPosition(existingCluster->localPosition());
759 potentialClusterPosition = (potentialClusterPosition + existingClusterPosition)/2;
760 potentialClusterId = hitSiDetElement->identifierOfPosition(potentialClusterPosition);
761 //FIXME - also need to tidy up any associations to the deleted cluster in the truth container too.
762 SCT_DetElClusterMap.erase(currentExistingClusterIter);
763
764
765 //Store HepMcParticleLink connected to the cluster removed from the collection
766 std::pair<PRD_MultiTruthCollection::iterator,PRD_MultiTruthCollection::iterator> saved_hit = sctPrdTruth->equal_range(existingCluster->identify());
767 for (PRD_MultiTruthCollection::iterator this_hit = saved_hit.first; this_hit != saved_hit.second; ++this_hit)
768 {
769 hit_vector.push_back(this_hit->second);
770 }
771 //Delete all the occurency of the currentCluster from the multi map
772 if (saved_hit.first != saved_hit.second) sctPrdTruth->erase(existingCluster->identify());
773
774 delete existingCluster;
775 ATH_MSG_VERBOSE("Merged two clusters.");
776 //break; // Should look for more than one possible merge.
777 }
778 }
779 ATH_MSG_INFO("After cluster merging there were " << SCT_DetElClusterMap.size() << " clusters in the SCT_DetElClusterMap.");
780 }
781 // check whether this is a trapezoid
782 const bool isTrapezoid(design->shape()==InDetDD::Trapezoid);
783 // prepare & create the siWidth
784 std::unique_ptr<InDet::SCT_Cluster> potentialClusterUniq = nullptr;
785 // Find length of strip at centre
786 const double clusterWidth(potentialClusterRDOList.size()*hitSiDetElement->phiPitch(potentialClusterPosition));
787 const std::pair<InDetDD::SiLocalPosition, InDetDD::SiLocalPosition> ends(design->endsOfStrip(potentialClusterPosition));
788 const double stripLength = std::abs(ends.first.xEta()-ends.second.xEta());
789 const InDet::SiWidth siWidth( Amg::Vector2D(int(potentialClusterRDOList.size()),1), Amg::Vector2D(clusterWidth,stripLength) );
790 // 2a) Cluster creation ------------------------------------
791 if (!m_clusterMaker.empty())
792 {
793 ATH_MSG_INFO("Using ClusterMakerTool to make cluster.");
794 // correct for the shift that will be applied in the cluster maker
795 // (only if surface charge emulation was switched off )
796 if (!m_sctEmulateSurfaceCharge && shift*shift > 0.)
797 {
798 potentialClusterPosition -= Amg::Vector2D(shift,0.);
799 }
800 // safe to compare m_sctTanLorentzAngleScalor with 1. since it is set not calculated
801 else if (m_sctTanLorentzAngleScalor != 1. && shift*shift > 0.)
802 {
803 // correct shift implied by the scaling of the Lorentz angle
804 const double newshift = 0.5*thickness*tanLorAng;
805 const double corr = ( shift - newshift );
806 potentialClusterPosition += Amg::Vector2D(corr,0.);
807 }
808 bool not_valid = false;
809 for (auto & i : potentialClusterRDOList)
810 {
811 if (!(i.is_valid()))
812 {
813 not_valid = true;
814 break;
815 }
816 }
817 if (not_valid)
818 {
819 continue;
820 }
821 potentialClusterUniq = std::make_unique<InDet::SCT_Cluster>(
822 m_clusterMaker->sctCluster(
823 potentialClusterId, potentialClusterPosition,
824 std::move(potentialClusterRDOList), siWidth, hitSiDetElement,
826 }
827 else
828 {
829 ATH_MSG_INFO("Making cluster locally.");
830 // you need to correct for the lorentz drift -- only if surface charge emulation was switched on
831 const double appliedShift = m_sctEmulateSurfaceCharge ? m_sctTanLorentzAngleScalor*shift : (1.-m_sctTanLorentzAngleScalor)*shift;
832 const Amg::Vector2D lcorrectedPosition = Amg::Vector2D(potentialClusterPosition.x()+appliedShift,potentialClusterPosition.y());
833 AmgSymMatrix(2) mat;
834 mat.setIdentity();
835 mat(Trk::locX,Trk::locX) = (clusterWidth*clusterWidth)/12.;
836 mat(Trk::locY,Trk::locY) = (stripLength*stripLength)/12.;
837 // rotation for endcap SCT
838 if(isTrapezoid && m_sctRotateEC)
839 {
840 const double Sn = hitSiDetElement->sinStereoLocal(intersection);
841 const double Sn2 = Sn*Sn;
842 const double Cs2 = 1.-Sn2;
843 //double W = detElement->phiPitch(*clusterLocalPosition)/detElement->phiPitch();
844 //double V0 = mat(Trk::locX,Trk::locX)*W*W;
845 const double V0 = mat(Trk::locX,Trk::locX);
846 const double V1 = mat(Trk::locY,Trk::locY);
847 mat(Trk::locX,Trk::locX) = (Cs2*V0+Sn2*V1);
848 mat(Trk::locY,Trk::locX) = (Sn*sqrt(Cs2)*(V0-V1));
849 mat(Trk::locY,Trk::locY) = (Sn2*V0+Cs2*V1);
850 }
851
852 // create a custom cluster
853 potentialClusterUniq = std::make_unique<InDet::SCT_Cluster>(
854 potentialClusterId, lcorrectedPosition,
855 std::vector<Identifier>(potentialClusterRDOList), siWidth, hitSiDetElement,
856 Amg::MatrixX(mat));
857 }
858
859 //SCT_DetElClusterMap takes ownership of the ptr
860 const auto it =
861 SCT_DetElClusterMap.insert(SCT_detElement_RIO_map::value_type(
862 waferID, potentialClusterUniq.release()));
863
864 //since we use this later
865 const InDet::SCT_Cluster* potentialCluster = it->second;
866
867 // Build Truth info for current cluster
868 if (currentLink.isValid()) {
870 sctPrdTruth->insert(std::make_pair(potentialCluster->identify(), currentLink));
871 ATH_MSG_DEBUG("Truth map filled with cluster" << potentialCluster << " and link = " << currentLink);
872 }
873 }
874 else
875 {
876 ATH_MSG_DEBUG("Particle link NOT valid!! Truth map NOT filled with cluster" << potentialCluster << " and link = " << currentLink);
877 }
878
879
880 for(const HepMcParticleLink& p: hit_vector){
881 sctPrdTruth->insert(std::make_pair(potentialCluster->identify(), p ));
882 }
883
884 hit_vector.clear();
885
886
887 } // end hit while
888
889 (void) m_sctClusterMap->insert(SCT_DetElClusterMap.begin(), SCT_DetElClusterMap.end());
890 }
891 return StatusCode::SUCCESS;
892}
893
894
895StatusCode SCT_FastDigitizationTool::createAndStoreRIOs(const EventContext& ctx)
896{
898 sctClusterContainer = std::make_unique<InDet::SCT_ClusterContainer>(m_sct_ID->wafer_hash_max());
899 if(!sctClusterContainer.isValid()) {
900 ATH_MSG_FATAL( "[ --- ] Could not create SCT_ClusterContainer");
901 return StatusCode::FAILURE;
902 }
903 sctClusterContainer->cleanup();
904
905 // --------------------------------------
906 // symlink the SCT Container
907 InDet::SiClusterContainer* symSiContainer=nullptr;
908 CHECK(evtStore()->symLink(sctClusterContainer.ptr(),symSiContainer));
909 ATH_MSG_DEBUG( "[ hitproc ] SCT_ClusterContainer symlinked to SiClusterContainer in StoreGate" );
910 // --------------------------------------
911
912 // Get SCT_DetectorElementCollection
914 const InDetDD::SiDetectorElementCollection* elements(sctDetEle.retrieve());
915 if (elements==nullptr) {
916 ATH_MSG_FATAL(m_SCTDetEleCollKey.fullKey() << " could not be retrieved");
917 return StatusCode::FAILURE;
918 }
919
920 SCT_detElement_RIO_map::iterator clusterMapGlobalIter = m_sctClusterMap->begin();
921 SCT_detElement_RIO_map::iterator endOfClusterMap = m_sctClusterMap->end();
922 for (; clusterMapGlobalIter != endOfClusterMap; clusterMapGlobalIter = m_sctClusterMap->upper_bound(clusterMapGlobalIter->first))
923 {
924 std::pair <SCT_detElement_RIO_map::iterator, SCT_detElement_RIO_map::iterator> range;
925 range = m_sctClusterMap->equal_range(clusterMapGlobalIter->first);
926 SCT_detElement_RIO_map::iterator firstDetElem = range.first;
927 const IdentifierHash waferID = firstDetElem->first;
928 const InDetDD::SiDetectorElement *detElement = elements->getDetectorElement(waferID);
929 InDet::SCT_ClusterCollection *clusterCollection = new InDet::SCT_ClusterCollection(waferID);
930 if (clusterCollection)
931 {
932 clusterCollection->setIdentifier(detElement->identify());
933 for ( SCT_detElement_RIO_map::iterator localClusterIter = range.first; localClusterIter != range.second; ++localClusterIter)
934 {
935 InDet::SCT_Cluster *sctCluster = localClusterIter->second;
936 sctCluster->setHashAndIndex(clusterCollection->identifyHash(),clusterCollection->size());
937 clusterCollection->push_back(sctCluster);
938 }
939 if (sctClusterContainer->addCollection(clusterCollection, clusterCollection->identifyHash()).isFailure())
940 {
941 ATH_MSG_WARNING( "Could not add collection to Identifiable container !" );
942 }
943 }
944 } // end for
945 m_sctClusterMap->clear();
946
947 return StatusCode::SUCCESS;
948}
949
951 const InDetDD::SiDetectorElement& sidetel,
952 //const Trk::Surface& surface,
953 double localStartX, double localStartY,
954 double localEndX, double localEndY,
955 double slopeYX,
956 double slopeZX,
957 const Amg::Vector2D& stripCenter,
958 int direction)
959{
960 double stepExitX = 0.;
961 double stepExitY = 0.;
962 double stepExitZ = 0.;
963 const double coef(1.);
964
965 // probably needs to be changed to rect/trapezoid
966 if (sidetel.isBarrel())
967 {
968 // the exit position of the new strip
969 double xExitPosition = stripCenter.x()+direction*0.5*sidetel.phiPitch(stripCenter);
970 stepExitX = xExitPosition-localStartX;
971 stepExitY = stepExitX*slopeYX;
972 stepExitZ = stepExitX*slopeZX;
973 }
974 else
975 {
976 // the end position of this particular strip
977 std::pair<Amg::Vector3D,Amg::Vector3D> stripEndGlobal = sidetel.endsOfStrip(stripCenter);
978 Amg::Vector3D oneStripEndLocal = coef*stripEndGlobal.first;
979 Amg::Vector3D twoStripEndLocal = coef*stripEndGlobal.second;
980
981 double oneStripPitch = sidetel.phiPitch(Amg::Vector2D(oneStripEndLocal.x(), oneStripEndLocal.y()));
982 double twoStripPitch = sidetel.phiPitch(Amg::Vector2D(twoStripEndLocal.x(), twoStripEndLocal.y()));
983 // now intersect track with border
984 Trk::LineIntersection2D intersectStripBorder(localStartX,localStartY,localEndX,localEndY,
985 oneStripEndLocal.x()+direction*0.5*oneStripPitch,oneStripEndLocal.y(),
986 twoStripEndLocal.x()+direction*0.5*twoStripPitch,twoStripEndLocal.y());
987 // the step in x
988 stepExitX = intersectStripBorder.interX - localStartX;
989 stepExitY = slopeYX*stepExitX;
990 stepExitZ = slopeZX*stepExitX;
991 }
992 return Amg::Vector3D(stepExitX,stepExitY,stepExitZ);
993}
994
995bool SCT_FastDigitizationTool::NeighbouringClusters(const std::vector<Identifier>& potentialClusterRDOList, const InDet::SCT_Cluster *existingCluster) const
996{
997 //---------------------------------------------------------------------------------
998 bool isNeighbour = false;
999 unsigned int countR(0);
1000 const std::vector<Identifier> &existingClusterRDOList = existingCluster->rdoList();
1001 std::vector<Identifier>::const_iterator potentialClusterRDOIter = potentialClusterRDOList.begin();
1002 for ( ; potentialClusterRDOIter != potentialClusterRDOList.end(); ++potentialClusterRDOIter)
1003 {
1004 ++countR;
1005 if (countR>100)
1006 {
1007 ATH_MSG_WARNING("Over 100 RDOs checked for the given cluster - bailing out!!");
1008 break;
1009 }
1010 std::vector<Identifier>::const_iterator existingClusterRDOIter = existingClusterRDOList.begin();
1011 for( ; existingClusterRDOIter != existingClusterRDOList.end(); ++existingClusterRDOIter)
1012 {
1013 if(std::abs(m_sct_ID->strip(*existingClusterRDOIter) - m_sct_ID->strip(*potentialClusterRDOIter)) < 2)
1014 {
1015 isNeighbour = true;
1016 break;
1017 }
1018 } // end of loop over RDOs in the current existing Cluster
1019 if (isNeighbour)
1020 {
1021 ATH_MSG_VERBOSE("The clusters are neighbours and can be merged.");
1022 break;
1023 }
1024 } // end of loop over RDOs in the potential cluster
1025 //---------------------------------------------------------------------------------
1026 return isNeighbour;
1027}
1028
1029
1030void SCT_FastDigitizationTool::Diffuse(HepGeom::Point3D<double>& localEntry, HepGeom::Point3D<double>& localExit, double shiftX, double shiftY ) {
1031
1032 double localEntryX = localEntry.x();
1033 double localExitX = localExit.x();
1034
1035 double signX = (localExitX - localEntryX) > 0 ? 1 : -1;
1036 localEntryX += shiftX * (-1) * signX;
1037 localExitX += shiftX * signX;
1038 localEntry.setX(localEntryX);
1039 localExit.setX(localExitX);
1040
1041 double localEntryY = localEntry.y();
1042 double localExitY = localExit.y();
1043
1044 double signY = (localExitY - localEntryY) > 0 ? 1 : -1;
1045 localEntryY += shiftY * (-1) * signY;
1046 localExitY += shiftY * signY;
1047
1048 //Check the effect in the endcap
1049 localEntry.setY(localEntryY);
1050 localExit.setY(localExitY);
1051
1052}
Scalar mag() const
mag 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)
#define CHECK(...)
Evaluate an expression and check for errors.
#define AmgSymMatrix(dim)
std::vector< xAOD::EventInfo::SubEvent >::const_iterator SubEventIterator
Definition IPileUpTool.h:22
the preferred mechanism to access information from the different event stores in a pileup job.
Digitize the SCT using an implementation of IPileUpTool.
This is an Identifier helper class for the SCT subdetector.
AtlasHitsVector< SiHit > SiHitCollection
A wrapper class for event-slot-local random engines.
Definition RNGWrapper.h:56
void setSeed(const std::string &algName, const EventContext &ctx)
Set the random seed using a string (e.g.
Definition RNGWrapper.h:154
CLHEP::HepRandomEngine * getEngine(const EventContext &ctx) const
Retrieve the random engine corresponding to the provided EventContext.
Definition RNGWrapper.h:108
size_type size() const
This is a "hash" representation of an Identifier.
bool is_valid() const
Check if id is in a valid state.
virtual DetectorShape shape() const
Shape of element.
Base class for the SCT module side design, extended by the Forward and Barrel module design.
int cells() const
number of readout stips within module side:
virtual std::pair< SiLocalPosition, SiLocalPosition > endsOfStrip(const SiLocalPosition &position) const override=0
give the ends of strips
Identifier for the strip or pixel cell.
Definition SiCellId.h:29
int phiIndex() const
Get phi index. Equivalent to strip().
Definition SiCellId.h:122
bool isValid() const
Test if its in a valid state.
Definition SiCellId.h:136
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.
virtual SiCellId cellIdFromIdentifier(const Identifier &identifier) const override final
SiCellId from Identifier.
virtual const SiDetectorDesign & design() const override final
access to the local description (inline):
double phiPitch() const
Pitch (inline methods).
std::pair< Amg::Vector3D, Amg::Vector3D > endsOfStrip(const Amg::Vector2D &position) const
Special method for SCT to retrieve the two ends of a "strip" Returned coordinates are in global frame...
double sinStereoLocal(const Amg::Vector2D &localPos) const
Angle of strip in local frame with respect to the etaAxis.
double length() const
Length in eta direction (z - barrel, r - endcap).
HepGeom::Point3D< double > hitLocalToLocal3D(const HepGeom::Point3D< double > &hitPosition) const
Same as previuos method but 3D.
virtual IdentifierHash identifyHash() const override final
identifier hash (inline)
virtual Identifier identify() const override final
identifier of this detector element (inline)
double hitDepthDirection() const
Directions of hit depth,phi,eta axes relative to reconstruction local position axes (LocalPosition).
Identifier identifierOfPosition(const Amg::Vector2D &localPos) const
Full identifier of the cell for a given position: assumes a raw local position (no Lorentz shift).
Amg::Vector2D rawLocalPositionOfCell(const SiCellId &cellId) const
Returns position (center) of cell.
Trk::Surface & surface()
Element Surface.
Gaudi::Property< int > m_vetoPileUpTruthLinks
PileUpToolBase(const std::string &type, const std::string &name, const IInterface *parent)
StatusCode processAllSubEvents(const EventContext &ctx)
BooleanProperty m_sctSmearLandau
if true : landau else: gauss
SG::WriteHandleKey< PRD_MultiTruthCollection > m_sctPrdTruthKey
the PRD truth map for SCT measurements
StringProperty m_randomEngineName
Name of the random number stream.
bool m_mergeCluster
enable the merging of neighbour SCT clusters >
const SCT_ID * m_sct_ID
Handle to the ID helper.
StatusCode digitize(const EventContext &ctx, TimedHitCollection< SiHit > &thpcsi)
ToolHandle< ISiLorentzAngleTool > m_lorentzAngleTool
DoubleProperty m_sctSmearPathLength
the 2.
virtual StatusCode initialize()
Called before processing physics events.
TimedHitCollection< SiHit > * m_thpcsi
static Amg::Vector3D stepToStripBorder(const InDetDD::SiDetectorElement &sidetel, double localStartX, double localStartY, double localEndX, double localEndY, double slopeYX, double slopeZX, const Amg::Vector2D &stripCenter, int direction)
IntegerProperty m_sctErrorStrategy
error strategy for the ClusterMaker
PublicToolHandle< InDet::ClusterMakerTool > m_clusterMaker
std::vector< SiHitCollection * > m_siHitCollList
name of the sub event hit collections.
StatusCode createAndStoreRIOs(const EventContext &ctx)
SCT_FastDigitizationTool(const std::string &type, const std::string &name, const IInterface *parent)
std::multimap< IdentifierHash, InDet::SCT_Cluster * > SCT_detElement_RIO_map
SCT_detElement_RIO_map * m_sctClusterMap
StatusCode prepareEvent(const EventContext &ctx, unsigned int)
SG::WriteHandleKey< InDet::SCT_ClusterContainer > m_sctClusterContainerKey
the SCT_ClusterContainer
StatusCode mergeEvent(const EventContext &ctx)
bool NeighbouringClusters(const std::vector< Identifier > &potentialClusterRDOList, const InDet::SCT_Cluster *existingCluster) const
IntegerProperty m_HardScatterSplittingMode
Process all SiHit or just those from signal or background events.
DoubleProperty m_sctMinimalPathCut
the 1.
ServiceHandle< IAthRNGSvc > m_rndmSvc
Random number service.
SG::ReadCondHandleKey< InDetDD::SiDetectorElementCollection > m_SCTDetEleCollKey
DoubleProperty m_sctTanLorentzAngleScalor
scale the lorentz angle effect
BooleanProperty m_sctEmulateSurfaceCharge
emulate the surface charge
static void Diffuse(HepGeom::Point3D< double > &localEntry, HepGeom::Point3D< double > &localExit, double shiftX, double shiftY)
BooleanProperty m_sctAnalogStripClustering
not being done in ATLAS: analog strip clustering
StatusCode processBunchXing(int bunchXing, SubEventIterator bSubEvents, SubEventIterator eSubEvents)
ServiceHandle< PileUpMergeSvc > m_mergeSvc
PileUp Merge service.
const_pointer_type retrieve()
const std::string & name() const
Return the StoreGate ID for the referenced object.
virtual bool isValid() override final
Can the handle be successfully dereferenced?
pointer_type ptr()
Dereference the pointer.
bool nextDetectorElement(const_iterator &b, const_iterator &e)
sets an iterator range with the hits of current detector element returns a bool when done
TimedVector::const_iterator const_iterator
void insert(const PileUpTimeEventIndex &timeEventIndex, const AtlasHitsVector< HIT > *inputCollection)
a smart pointer to a hit that also provides access to the extended timing info of the host event.
Definition TimedHitPtr.h:18
unsigned short eventId() const
the index of the component event in PileUpEventInfo.
Definition TimedHitPtr.h:47
const Amg::Vector2D & localPosition() const
return the local position reference
Identifier identify() const
return the identifier
void setHashAndIndex(unsigned short collHash, unsigned short objIndex)
TEMP for testing: might make some classes friends later ...
const std::vector< Identifier > & rdoList() const
return the List of rdo identifiers (pointers)
virtual bool insideLoc2(const Amg::Vector2D &locpo, double tol2=0.) const =0
Extend the interface to for single inside Loc 1 / Loc2 tests.
Abstract Base Class for tracking surfaces.
Definition Surface.h:79
virtual const SurfaceBounds & bounds() const =0
Surface Bounds method.
std::vector< std::string > intersection(std::vector< std::string > &v1, std::vector< std::string > &v2)
Eigen::Matrix< double, Eigen::Dynamic, Eigen::Dynamic > MatrixX
Dynamic Matrix - dynamic allocation.
Eigen::Matrix< double, 2, 1 > Vector2D
Eigen::Matrix< double, 3, 1 > Vector3D
bool ignoreTruthLink(const T &p, bool vetoPileUp)
Helper function for SDO creation in PileUpTools.
@ locY
local cartesian
Definition ParamDefs.h:38
@ locX
Definition ParamDefs.h:37
#define unlikely(x)
std::list< value_t > type
type of the collection of timed data object
a struct encapsulating the identifier of a pile-up event
index_type index() const
the index of the component event in PileUpEventInfo
PileUpType type() const
the pileup type - minbias, cavern, beam halo, signal?
time_type time() const
bunch xing time in ns