ATLAS Offline Software
Loading...
Searching...
No Matches
SCT_FastDigitizationTool.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2024 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 potentialClusterPosition *= 1./totalWeight;
726 /*const */Identifier potentialClusterId = hitSiDetElement->identifierOfPosition(potentialClusterPosition);
727 if (!potentialClusterId.is_valid()) {continue;}
728
729 const IdentifierHash waferID = m_sct_ID->wafer_hash(hitSiDetElement->identify());
730
731 // merging clusters
732 if(m_mergeCluster){
733 unsigned int countC(0);
734 ATH_MSG_INFO("Before cluster merging there were " << SCT_DetElClusterMap.size() << " clusters in the SCT_DetElClusterMap.");
735 for(SCT_detElement_RIO_map::iterator existingClusterIter = SCT_DetElClusterMap.begin(); existingClusterIter != SCT_DetElClusterMap.end();)
736 {
737 ++countC;
738 if (countC>100)
739 {
740 ATH_MSG_WARNING("Over 100 clusters checked for merging - bailing out!!");
741 break;
742 }
743 if (m_sct_ID->wafer_hash(((existingClusterIter->second)->detectorElement())->identify()) != waferID) {continue;}
744 //make a temporary to use within the loop and possibly erase - increment the main interator at the same time.
745 SCT_detElement_RIO_map::iterator currentExistingClusterIter = existingClusterIter++;
746
747 const InDet::SCT_Cluster *existingCluster = (currentExistingClusterIter->second);
748 bool isNeighbour = this->NeighbouringClusters(potentialClusterRDOList, existingCluster);
749 if(isNeighbour)
750 {
751 //Merge the clusters
752 const std::vector<Identifier> &existingClusterRDOList = existingCluster->rdoList();
753 potentialClusterRDOList.insert(potentialClusterRDOList.end(), existingClusterRDOList.begin(), existingClusterRDOList.end() );
754 Amg::Vector2D existingClusterPosition(existingCluster->localPosition());
755 potentialClusterPosition = (potentialClusterPosition + existingClusterPosition)/2;
756 potentialClusterId = hitSiDetElement->identifierOfPosition(potentialClusterPosition);
757 //FIXME - also need to tidy up any associations to the deleted cluster in the truth container too.
758 SCT_DetElClusterMap.erase(currentExistingClusterIter);
759
760
761 //Store HepMcParticleLink connected to the cluster removed from the collection
762 std::pair<PRD_MultiTruthCollection::iterator,PRD_MultiTruthCollection::iterator> saved_hit = sctPrdTruth->equal_range(existingCluster->identify());
763 for (PRD_MultiTruthCollection::iterator this_hit = saved_hit.first; this_hit != saved_hit.second; ++this_hit)
764 {
765 hit_vector.push_back(this_hit->second);
766 }
767 //Delete all the occurency of the currentCluster from the multi map
768 if (saved_hit.first != saved_hit.second) sctPrdTruth->erase(existingCluster->identify());
769
770 delete existingCluster;
771 ATH_MSG_VERBOSE("Merged two clusters.");
772 //break; // Should look for more than one possible merge.
773 }
774 }
775 ATH_MSG_INFO("After cluster merging there were " << SCT_DetElClusterMap.size() << " clusters in the SCT_DetElClusterMap.");
776 }
777 // check whether this is a trapezoid
778 const bool isTrapezoid(design->shape()==InDetDD::Trapezoid);
779 // prepare & create the siWidth
780 std::unique_ptr<InDet::SCT_Cluster> potentialClusterUniq = nullptr;
781 // Find length of strip at centre
782 const double clusterWidth(potentialClusterRDOList.size()*hitSiDetElement->phiPitch(potentialClusterPosition));
783 const std::pair<InDetDD::SiLocalPosition, InDetDD::SiLocalPosition> ends(design->endsOfStrip(potentialClusterPosition));
784 const double stripLength = std::abs(ends.first.xEta()-ends.second.xEta());
785 const InDet::SiWidth siWidth( Amg::Vector2D(int(potentialClusterRDOList.size()),1), Amg::Vector2D(clusterWidth,stripLength) );
786 // 2a) Cluster creation ------------------------------------
787 if (!m_clusterMaker.empty())
788 {
789 ATH_MSG_INFO("Using ClusterMakerTool to make cluster.");
790 // correct for the shift that will be applied in the cluster maker
791 // (only if surface charge emulation was switched off )
792 if (!m_sctEmulateSurfaceCharge && shift*shift > 0.)
793 {
794 potentialClusterPosition -= Amg::Vector2D(shift,0.);
795 }
796 // safe to compare m_sctTanLorentzAngleScalor with 1. since it is set not calculated
797 else if (m_sctTanLorentzAngleScalor != 1. && shift*shift > 0.)
798 {
799 // correct shift implied by the scaling of the Lorentz angle
800 const double newshift = 0.5*thickness*tanLorAng;
801 const double corr = ( shift - newshift );
802 potentialClusterPosition += Amg::Vector2D(corr,0.);
803 }
804 bool not_valid = false;
805 for (auto & i : potentialClusterRDOList)
806 {
807 if (!(i.is_valid()))
808 {
809 not_valid = true;
810 break;
811 }
812 }
813 if (not_valid)
814 {
815 continue;
816 }
817 potentialClusterUniq = std::make_unique<InDet::SCT_Cluster>(
818 m_clusterMaker->sctCluster(
819 potentialClusterId, potentialClusterPosition,
820 std::vector<Identifier>(potentialClusterRDOList), siWidth, hitSiDetElement,
822 }
823 else
824 {
825 ATH_MSG_INFO("Making cluster locally.");
826 // you need to correct for the lorentz drift -- only if surface charge emulation was switched on
827 const double appliedShift = m_sctEmulateSurfaceCharge ? m_sctTanLorentzAngleScalor*shift : (1.-m_sctTanLorentzAngleScalor)*shift;
828 const Amg::Vector2D lcorrectedPosition = Amg::Vector2D(potentialClusterPosition.x()+appliedShift,potentialClusterPosition.y());
829 AmgSymMatrix(2) mat;
830 mat.setIdentity();
831 mat(Trk::locX,Trk::locX) = (clusterWidth*clusterWidth)/12.;
832 mat(Trk::locY,Trk::locY) = (stripLength*stripLength)/12.;
833 // rotation for endcap SCT
834 if(isTrapezoid && m_sctRotateEC)
835 {
836 const double Sn = hitSiDetElement->sinStereoLocal(intersection);
837 const double Sn2 = Sn*Sn;
838 const double Cs2 = 1.-Sn2;
839 //double W = detElement->phiPitch(*clusterLocalPosition)/detElement->phiPitch();
840 //double V0 = mat(Trk::locX,Trk::locX)*W*W;
841 const double V0 = mat(Trk::locX,Trk::locX);
842 const double V1 = mat(Trk::locY,Trk::locY);
843 mat(Trk::locX,Trk::locX) = (Cs2*V0+Sn2*V1);
844 mat(Trk::locY,Trk::locX) = (Sn*sqrt(Cs2)*(V0-V1));
845 mat(Trk::locY,Trk::locY) = (Sn2*V0+Cs2*V1);
846 }
847
848 // create a custom cluster
849 potentialClusterUniq = std::make_unique<InDet::SCT_Cluster>(
850 potentialClusterId, lcorrectedPosition,
851 std::vector<Identifier>(potentialClusterRDOList), siWidth, hitSiDetElement,
852 Amg::MatrixX(mat));
853 }
854
855 //SCT_DetElClusterMap takes ownership of the ptr
856 const auto it =
857 SCT_DetElClusterMap.insert(SCT_detElement_RIO_map::value_type(
858 waferID, potentialClusterUniq.release()));
859
860 //since we use this later
861 const InDet::SCT_Cluster* potentialCluster = it->second;
862
863 // Build Truth info for current cluster
864 if (currentLink.isValid()) {
866 sctPrdTruth->insert(std::make_pair(potentialCluster->identify(), currentLink));
867 ATH_MSG_DEBUG("Truth map filled with cluster" << potentialCluster << " and link = " << currentLink);
868 }
869 }
870 else
871 {
872 ATH_MSG_DEBUG("Particle link NOT valid!! Truth map NOT filled with cluster" << potentialCluster << " and link = " << currentLink);
873 }
874
875
876 for(const HepMcParticleLink& p: hit_vector){
877 sctPrdTruth->insert(std::make_pair(potentialCluster->identify(), p ));
878 }
879
880 hit_vector.clear();
881
882
883 } // end hit while
884
885 (void) m_sctClusterMap->insert(SCT_DetElClusterMap.begin(), SCT_DetElClusterMap.end());
886 }
887 return StatusCode::SUCCESS;
888}
889
890
891StatusCode SCT_FastDigitizationTool::createAndStoreRIOs(const EventContext& ctx)
892{
894 sctClusterContainer = std::make_unique<InDet::SCT_ClusterContainer>(m_sct_ID->wafer_hash_max());
895 if(!sctClusterContainer.isValid()) {
896 ATH_MSG_FATAL( "[ --- ] Could not create SCT_ClusterContainer");
897 return StatusCode::FAILURE;
898 }
899 sctClusterContainer->cleanup();
900
901 // --------------------------------------
902 // symlink the SCT Container
903 InDet::SiClusterContainer* symSiContainer=nullptr;
904 CHECK(evtStore()->symLink(sctClusterContainer.ptr(),symSiContainer));
905 ATH_MSG_DEBUG( "[ hitproc ] SCT_ClusterContainer symlinked to SiClusterContainer in StoreGate" );
906 // --------------------------------------
907
908 // Get SCT_DetectorElementCollection
910 const InDetDD::SiDetectorElementCollection* elements(sctDetEle.retrieve());
911 if (elements==nullptr) {
912 ATH_MSG_FATAL(m_SCTDetEleCollKey.fullKey() << " could not be retrieved");
913 return StatusCode::FAILURE;
914 }
915
916 SCT_detElement_RIO_map::iterator clusterMapGlobalIter = m_sctClusterMap->begin();
917 SCT_detElement_RIO_map::iterator endOfClusterMap = m_sctClusterMap->end();
918 for (; clusterMapGlobalIter != endOfClusterMap; clusterMapGlobalIter = m_sctClusterMap->upper_bound(clusterMapGlobalIter->first))
919 {
920 std::pair <SCT_detElement_RIO_map::iterator, SCT_detElement_RIO_map::iterator> range;
921 range = m_sctClusterMap->equal_range(clusterMapGlobalIter->first);
922 SCT_detElement_RIO_map::iterator firstDetElem = range.first;
923 const IdentifierHash waferID = firstDetElem->first;
924 const InDetDD::SiDetectorElement *detElement = elements->getDetectorElement(waferID);
925 InDet::SCT_ClusterCollection *clusterCollection = new InDet::SCT_ClusterCollection(waferID);
926 if (clusterCollection)
927 {
928 clusterCollection->setIdentifier(detElement->identify());
929 for ( SCT_detElement_RIO_map::iterator localClusterIter = range.first; localClusterIter != range.second; ++localClusterIter)
930 {
931 InDet::SCT_Cluster *sctCluster = localClusterIter->second;
932 sctCluster->setHashAndIndex(clusterCollection->identifyHash(),clusterCollection->size());
933 clusterCollection->push_back(sctCluster);
934 }
935 if (sctClusterContainer->addCollection(clusterCollection, clusterCollection->identifyHash()).isFailure())
936 {
937 ATH_MSG_WARNING( "Could not add collection to Identifiable container !" );
938 }
939 }
940 } // end for
941 m_sctClusterMap->clear();
942
943 return StatusCode::SUCCESS;
944}
945
947 const InDetDD::SiDetectorElement& sidetel,
948 //const Trk::Surface& surface,
949 double localStartX, double localStartY,
950 double localEndX, double localEndY,
951 double slopeYX,
952 double slopeZX,
953 const Amg::Vector2D& stripCenter,
954 int direction)
955{
956 double stepExitX = 0.;
957 double stepExitY = 0.;
958 double stepExitZ = 0.;
959 const double coef(1.);
960
961 // probably needs to be changed to rect/trapezoid
962 if (sidetel.isBarrel())
963 {
964 // the exit position of the new strip
965 double xExitPosition = stripCenter.x()+direction*0.5*sidetel.phiPitch(stripCenter);
966 stepExitX = xExitPosition-localStartX;
967 stepExitY = stepExitX*slopeYX;
968 stepExitZ = stepExitX*slopeZX;
969 }
970 else
971 {
972 // the end position of this particular strip
973 std::pair<Amg::Vector3D,Amg::Vector3D> stripEndGlobal = sidetel.endsOfStrip(stripCenter);
974 Amg::Vector3D oneStripEndLocal = coef*stripEndGlobal.first;
975 Amg::Vector3D twoStripEndLocal = coef*stripEndGlobal.second;
976
977 double oneStripPitch = sidetel.phiPitch(Amg::Vector2D(oneStripEndLocal.x(), oneStripEndLocal.y()));
978 double twoStripPitch = sidetel.phiPitch(Amg::Vector2D(twoStripEndLocal.x(), twoStripEndLocal.y()));
979 // now intersect track with border
980 Trk::LineIntersection2D intersectStripBorder(localStartX,localStartY,localEndX,localEndY,
981 oneStripEndLocal.x()+direction*0.5*oneStripPitch,oneStripEndLocal.y(),
982 twoStripEndLocal.x()+direction*0.5*twoStripPitch,twoStripEndLocal.y());
983 // the step in x
984 stepExitX = intersectStripBorder.interX - localStartX;
985 stepExitY = slopeYX*stepExitX;
986 stepExitZ = slopeZX*stepExitX;
987 }
988 return Amg::Vector3D(stepExitX,stepExitY,stepExitZ);
989}
990
991bool SCT_FastDigitizationTool::NeighbouringClusters(const std::vector<Identifier>& potentialClusterRDOList, const InDet::SCT_Cluster *existingCluster) const
992{
993 //---------------------------------------------------------------------------------
994 bool isNeighbour = false;
995 unsigned int countR(0);
996 const std::vector<Identifier> &existingClusterRDOList = existingCluster->rdoList();
997 std::vector<Identifier>::const_iterator potentialClusterRDOIter = potentialClusterRDOList.begin();
998 for ( ; potentialClusterRDOIter != potentialClusterRDOList.end(); ++potentialClusterRDOIter)
999 {
1000 ++countR;
1001 if (countR>100)
1002 {
1003 ATH_MSG_WARNING("Over 100 RDOs checked for the given cluster - bailing out!!");
1004 break;
1005 }
1006 std::vector<Identifier>::const_iterator existingClusterRDOIter = existingClusterRDOList.begin();
1007 for( ; existingClusterRDOIter != existingClusterRDOList.end(); ++existingClusterRDOIter)
1008 {
1009 if(std::abs(m_sct_ID->strip(*existingClusterRDOIter) - m_sct_ID->strip(*potentialClusterRDOIter)) < 2)
1010 {
1011 isNeighbour = true;
1012 break;
1013 }
1014 } // end of loop over RDOs in the current existing Cluster
1015 if (isNeighbour)
1016 {
1017 ATH_MSG_VERBOSE("The clusters are neighbours and can be merged.");
1018 break;
1019 }
1020 } // end of loop over RDOs in the potential cluster
1021 //---------------------------------------------------------------------------------
1022 return isNeighbour;
1023}
1024
1025
1026void SCT_FastDigitizationTool::Diffuse(HepGeom::Point3D<double>& localEntry, HepGeom::Point3D<double>& localExit, double shiftX, double shiftY ) {
1027
1028 double localEntryX = localEntry.x();
1029 double localExitX = localExit.x();
1030
1031 double signX = (localExitX - localEntryX) > 0 ? 1 : -1;
1032 localEntryX += shiftX * (-1) * signX;
1033 localExitX += shiftX * signX;
1034 localEntry.setX(localEntryX);
1035 localExit.setX(localExitX);
1036
1037 double localEntryY = localEntry.y();
1038 double localExitY = localExit.y();
1039
1040 double signY = (localExitY - localEntryY) > 0 ? 1 : -1;
1041 localEntryY += shiftY * (-1) * signY;
1042 localExitY += shiftY * signY;
1043
1044 //Check the effect in the endcap
1045 localEntry.setY(localEntryY);
1046 localExit.setY(localExitY);
1047
1048}
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:169
CLHEP::HepRandomEngine * getEngine(const EventContext &ctx) const
Retrieve the random engine corresponding to the provided EventContext.
Definition RNGWrapper.h:134
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.
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
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