21 #include "GaudiKernel/SystemOfUnits.h"
40 #include "CLHEP/Vector/ThreeVector.h"
41 #include "CLHEP/Random/RandFlat.h"
42 #include "CLHEP/Random/RandGaussZiggurat.h"
45 #include "Identifier/Identifier.h"
51 static const unsigned int maskHT=0x04020100;
54 const std::string &
name,
84 return StatusCode::FAILURE;
129 TimedHitCollList hitCollList;
132 bSubEvents, eSubEvents).isSuccess()) &&
133 hitCollList.empty()) {
135 return StatusCode::FAILURE;
137 ATH_MSG_VERBOSE(hitCollList.size() <<
" TRTUncompressedHitCollections with key " <<
144 for( ; iColl != endColl; ++iColl) {
147 ATH_MSG_DEBUG(
"TRTUncompressedHitCollection found with " << hitCollPtr->
size() <<
150 <<
" index: " << timeIndex.
index()
151 <<
" type: " << timeIndex.
type());
156 return StatusCode::SUCCESS;
166 return StatusCode::SUCCESS;
175 static const float eff_corr_pileup_dependence = -0.0005;
176 static const float res1_corr_pileup_dependence = 0.005;
177 static const float res2_corr_pileup_dependence = 0.015;
184 static const float tailRes = 3.600;
185 static const float coreFracEndcap_Xe = 0.40;
186 static const float coreFracEndcap_Ar = 0.40;
187 static const float coreFracBarrel_Xe = 0.250;
188 static const float coreFracBarrel_Ar = 0.250;
191 static const float eff_BarrelA_Xe = 0.840;
192 static const float eff_EndcapA_Xe = 0.875;
193 static const float eff_BarrelC_Xe = 0.833;
194 static const float eff_EndcapC_Xe = 0.894;
195 static const float eff_BarrelA_Ar = 0.933;
196 static const float eff_EndcapA_Ar = 0.949;
197 static const float eff_BarrelC_Ar = 0.937;
198 static const float eff_EndcapC_Ar = 0.977;
199 static const float err_Barrel_Xe = 0.997;
200 static const float err_Endcap_Xe = 1.065;
201 static const float err_Barrel_Ar = 1.020;
202 static const float err_Endcap_Ar = 1.040;
204 static const float coreRes_Barrel_Xe = 0.4;
205 static const float coreRes_Endcap_Xe = 0.5;
206 static const float coreRes_Barrel_Ar = 0.4;
207 static const float coreRes_Endcap_Ar = 0.5;
209 m_cFit[ 0 ][ 0 ] = effcorr*eff_BarrelA_Xe;
210 m_cFit[ 0 ][ 1 ] = err_Barrel_Xe;
211 m_cFit[ 0 ][ 2 ] = coreFracBarrel_Xe;
212 m_cFit[ 0 ][ 3 ] = res1corr*coreRes_Barrel_Xe;
213 m_cFit[ 0 ][ 4 ] = res2corr*tailRes;
214 m_cFit[ 1 ][ 0 ] = effcorr*eff_EndcapA_Xe;
215 m_cFit[ 1 ][ 1 ] = err_Endcap_Xe;
216 m_cFit[ 1 ][ 2 ] = coreFracEndcap_Xe;
217 m_cFit[ 1 ][ 3 ] = res1corr*coreRes_Endcap_Xe;
218 m_cFit[ 1 ][ 4 ] = res2corr*tailRes;
219 m_cFit[ 2 ][ 0 ] = effcorr*eff_BarrelC_Xe;
220 m_cFit[ 2 ][ 1 ] = err_Barrel_Xe;
221 m_cFit[ 2 ][ 2 ] = coreFracBarrel_Xe;
222 m_cFit[ 2 ][ 3 ] = res1corr*coreRes_Barrel_Xe;
223 m_cFit[ 2 ][ 4 ] = res2corr*tailRes;
224 m_cFit[ 3 ][ 0 ] = effcorr*eff_EndcapC_Xe;
225 m_cFit[ 3 ][ 1 ] = err_Endcap_Xe;
226 m_cFit[ 3 ][ 2 ] = coreFracEndcap_Xe;
227 m_cFit[ 3 ][ 3 ] = res1corr*coreRes_Endcap_Xe;
228 m_cFit[ 3 ][ 4 ] = res2corr*tailRes;
229 m_cFit[ 4 ][ 0 ] = effcorr*eff_BarrelA_Ar;
230 m_cFit[ 4 ][ 1 ] = err_Barrel_Ar;
231 m_cFit[ 4 ][ 2 ] = coreFracBarrel_Ar;
232 m_cFit[ 4 ][ 3 ] = res1corr*coreRes_Barrel_Ar;
233 m_cFit[ 4 ][ 4 ] = res2corr*tailRes;
234 m_cFit[ 5 ][ 0 ] = effcorr*eff_EndcapA_Ar;
235 m_cFit[ 5 ][ 1 ] = err_Endcap_Ar;
236 m_cFit[ 5 ][ 2 ] = coreFracEndcap_Ar;
237 m_cFit[ 5 ][ 3 ] = res1corr*coreRes_Endcap_Ar;
238 m_cFit[ 5 ][ 4 ] = res2corr*tailRes;
239 m_cFit[ 6 ][ 0 ] = effcorr*eff_BarrelC_Ar;
240 m_cFit[ 6 ][ 1 ] = err_Barrel_Ar;
241 m_cFit[ 6 ][ 2 ] = coreFracBarrel_Ar;
242 m_cFit[ 6 ][ 3 ] = res1corr*coreRes_Barrel_Ar;
243 m_cFit[ 6 ][ 4 ] = res2corr*tailRes;
244 m_cFit[ 7 ][ 0 ] = effcorr*eff_EndcapC_Ar;
245 m_cFit[ 7 ][ 1 ] = err_Endcap_Ar;
246 m_cFit[ 7 ][ 2 ] = coreFracEndcap_Ar;
247 m_cFit[ 7 ][ 3 ] = res1corr*coreRes_Endcap_Ar;
248 m_cFit[ 7 ][ 4 ] = res2corr*tailRes;
250 return StatusCode::SUCCESS;
254 CLHEP::HepRandomEngine* rndmEngine,
259 trtPrdTruth = std::make_unique< PRD_MultiTruthCollection >();
260 if ( !trtPrdTruth.
isValid() ) {
262 return StatusCode::FAILURE;
264 ATH_MSG_DEBUG(
"PRD_MultiTruthCollection " << trtPrdTruth.
name() <<
" registered in StoreGate" );
269 if(eventInfoContainer.
isValid()){
278 if(
sc != StatusCode::SUCCESS)
return sc;
285 for ( ; itr1 != itr2; ++itr1 ) {
290 int hitID = hit->GetHitID();
292 if ( hitID & 0xc0000000 ) {
293 ATH_MSG_ERROR(
"Hit ID not Valid (" << MSG::hex << hitID <<
")" << MSG::dec );
303 ATH_MSG_ERROR(
"Ignoring simhits with suspicious identifier (1)" );
312 int idx = (
BEC > 0 ?
BEC : 2 -
BEC ) + 4 * isArgon - 1;
321 if ( CLHEP::RandFlat::shoot( rndmEngine ) < ( 1. -
efficiency ) )
continue;
336 double tailSmearing = CLHEP::RandFlat::shoot( rndmEngine );
337 dR = CLHEP::RandGaussZiggurat::shoot( rndmEngine, 0., ( tailSmearing <
m_cFit[
idx ][ 2 ] ?
m_cFit[
idx ][ 3 ] :
m_cFit[
idx ][ 4 ] ) ) * sigmaTrt;
340 dR = 2. - driftRadiusLoc;
344 while ( driftRadiusLoc + dR > 2. || driftRadiusLoc + dR < 0. );
345 double smearedRadius = driftRadiusLoc + dR;
348 std::vector< Identifier > rdoList = { straw_id };
356 unsigned int word = 0x00007c00;
360 int particleEncoding = hit->GetParticleEncoding();
361 float kineticEnergy = hit->GetKineticEnergy();
365 double position = ( std::abs(
BEC) == 1 ? hitGlobalPosition.z() : hitGlobalPosition.perp() );
368 if ( abs( particleEncoding ) == 11 && kineticEnergy > 5000. ) {
375 if ( CLHEP::RandFlat::shoot( rndmEngine ) < probability ) word |= maskHT;
379 double eta = hitGlobalPosition.pseudoRapidity();
382 float p = kineticEnergy;
384 if ( abs( particleEncoding ) == 11 &&
p > 5000. ) {
386 if ( CLHEP::RandFlat::shoot( rndmEngine ) < probability ) word |= maskHT;
388 else if ( abs( particleEncoding ) == 13 || abs( particleEncoding ) > 100 ) {
390 if ( CLHEP::RandFlat::shoot( rndmEngine ) < probability ) word |= maskHT;
399 std::move(hitErrorMatrix),
405 m_driftCircleMap.insert( std::multimap< Identifier, InDet::TRT_DriftCircle * >::value_type( straw_id, trtDriftCircle ) );
407 if ( particleLink.
isValid() ) {
409 trtPrdTruth->insert( std::make_pair( trtDriftCircle->
identify(), particleLink ) );
410 ATH_MSG_DEBUG(
"Truth map filled with cluster " << trtDriftCircle <<
" and link = " << particleLink );
414 ATH_MSG_DEBUG(
"Particle link NOT valid!! Truth map NOT filled with cluster " << trtDriftCircle <<
" and link = " << particleLink );
420 return StatusCode::SUCCESS;
426 ATH_MSG_DEBUG(
"TRTFastDigitizationTool::processAllSubEvents()" );
430 HitCollectionTimedList hitCollectionTimedList;
431 unsigned int numberOfSimHits = 0;
432 if (
m_mergeSvc->retrieveSubEvtsData(
m_trtHitCollectionKey.value(), hitCollectionTimedList, numberOfSimHits ).isFailure() && hitCollectionTimedList.empty() ) {
434 return StatusCode::FAILURE;
442 for (
auto & itr : hitCollectionTimedList) {
453 rngWrapper->
setSeed( rngName, ctx );
454 CLHEP::HepRandomEngine *rndmEngine = rngWrapper->
getEngine(ctx);
462 return StatusCode::SUCCESS;
473 rngWrapper->
setSeed( rngName, ctx );
474 CLHEP::HepRandomEngine *rndmEngine = rngWrapper->
getEngine(ctx);
489 return StatusCode::SUCCESS;
498 if ( !trtDriftCircleContainer.
isValid() ) {
499 ATH_MSG_FATAL(
"Could not create TRT_DriftCircleContainer" );
500 return StatusCode::FAILURE;
502 ATH_MSG_DEBUG(
"InDet::TRT_DriftCircleContainer " << trtDriftCircleContainer.
name() <<
" registered in StoreGate" );
514 std::multimap< IdentifierHash, InDet::TRT_DriftCircle * > idHashMap;
519 std::pair< DriftCircleMapItr, DriftCircleMapItr > hitsInOneStraw =
m_driftCircleMap.equal_range( trtid );
526 for ( DriftCircleMapItr itr2 = ++( hitsInOneStraw.first ); itr2 != hitsInOneStraw.second; ++itr2 ) {
528 if(trtDriftCircle2->
getWord() & maskHT) isHT =
true;
529 delete trtDriftCircle2;
533 if( !(trtDriftCircle->
getWord() & maskHT) && !isHT && numberOfHitsInOneStraw > 1) {
534 unsigned int newword = 0;
535 if(highTRMergeProb*(numberOfHitsInOneStraw-1) > CLHEP::RandFlat::shoot( rndmEngine )) newword += 1 << (26-9);
536 const unsigned int newword2 = newword;
538 const std::vector<Identifier> &rdolist = trtDriftCircle->
rdoList();
543 std::vector<Identifier>(rdolist),
548 std::multimap<IdentifierHash, InDet::TRT_DriftCircle*>::value_type(
549 hash, trtDriftCircle2));
550 delete trtDriftCircle;
553 idHashMap.insert( std::multimap<IdentifierHash, InDet::TRT_DriftCircle * >::value_type(
hash, trtDriftCircle ) );
558 for ( HashMapItr itr = idHashMap.begin(); itr != idHashMap.end(); itr = idHashMap.upper_bound( itr->first ) ) {
560 std::pair< HashMapItr, HashMapItr > itrPair = idHashMap.equal_range( itr->first );
566 trtDriftCircleCollection->setIdentifier( trtBaseElement->
identify() );
568 for ( HashMapItr itr2 = itrPair.first; itr2 != itrPair.second; ++itr2 ) {
570 trtDriftCircle->
setHashAndIndex( trtDriftCircleCollection->identifyHash(), trtDriftCircleCollection->size() );
571 trtDriftCircleCollection->push_back( trtDriftCircle );
574 if ( trtDriftCircleContainer->addCollection( trtDriftCircleCollection,
hash ).isFailure() ) {
575 ATH_MSG_WARNING(
"Could not add collection to Identifyable container" );
582 return StatusCode::SUCCESS;
588 HepGeom::Vector3D< double > vecEnter( hit->GetPreStepX(), hit->GetPreStepY(), hit->GetPreStepZ() );
589 HepGeom::Vector3D< double > vecExit( hit->GetPostStepX(), hit->GetPostStepY(), hit->GetPostStepZ() );
591 HepGeom::Vector3D< double > vecDir = vecExit - vecEnter;
592 static const HepGeom::Vector3D< double > vecStraw( 0., 0., 1. );
594 vecDir = vecDir.unit();
597 if ( std::abs( vecDir.x() ) < 1.0e-6 && std::abs( vecDir.y() ) < 1.0e-6 ) {
601 double a = vecEnter.dot( vecStraw );
602 double b = vecEnter.dot( vecDir );
603 double c = vecDir.dot( vecStraw );
605 double paramStraw = (
a -
b*
c ) / ( 1. -
c*
c );
606 double paramTrack = -(
b -
a*
c ) / ( 1. -
c*
c );
608 HepGeom::Vector3D<double> vecClosestAppr = vecEnter + paramTrack * vecDir - paramStraw * vecStraw;
622 const int mask( 0x0000001F );
623 const int word_shift( 5 );
625 if ( hitID & 0x00200000 ) {
626 int strawID = hitID &
mask;
627 int planeID = ( hitID >> word_shift ) &
mask;
628 int sectorID = ( hitID >> 2 * word_shift ) &
mask;
629 int wheelID = ( hitID >> 3 * word_shift ) &
mask;
630 int trtID = ( hitID >> 4 * word_shift );
633 trtID = ( trtID == 3 ? 0 : 1 );
636 if ( endcapElement ) {
638 layer_id = endcapElement->
identify();
642 ATH_MSG_ERROR(
"Could not find detector element for endcap identifier with (ipos,iwheel,isector,iplane,istraw) = ("
643 << trtID <<
", " << wheelID <<
", " << sectorID <<
", " << planeID <<
", " << strawID <<
")" <<
endmsg
644 <<
"If this happens very rarely, don't be alarmed (it is a Geant4 'feature')" <<
endmsg
645 <<
"If it happens a lot, you probably have misconfigured geometry in the sim. job." );
651 int strawID = hitID &
mask;
652 int layerID = ( hitID >> word_shift ) &
mask;
653 int moduleID = ( hitID >> 2 * word_shift ) &
mask;
654 int ringID = ( hitID >> 3 * word_shift ) &
mask;
655 int trtID = ( hitID >> 4 * word_shift );
658 if ( barrelElement ) {
660 layer_id = barrelElement->
identify();
663 ATH_MSG_ERROR(
"Could not find detector element for barrel identifier with (ipos,iring,imod,ilayer,istraw) = ("
664 << trtID <<
", " << ringID <<
", " << moduleID <<
", " << layerID <<
", " << strawID <<
")" );
676 int hitID = hit->GetHitID();
677 const HepGeom::Point3D< double > hitPreStep( hit->GetPreStepX(), hit->GetPreStepY(), hit->GetPreStepZ() );
679 const int mask( 0x0000001F );
680 const int word_shift( 5 );
682 if ( hitID & 0x00200000 ) {
683 int strawID = hitID &
mask;
684 int planeID = ( hitID >> word_shift ) &
mask;
685 int sectorID = ( hitID >> 2 * word_shift ) &
mask;
686 int wheelID = ( hitID >> 3 * word_shift ) &
mask;
687 int trtID = ( hitID >> 4 * word_shift );
690 trtID = ( trtID == 3 ? 0 : 1 );
693 if ( endcapElement ) {
699 int strawID = hitID &
mask;
700 int layerID = ( hitID >> word_shift ) &
mask;
701 int moduleID = ( hitID >> 2 * word_shift ) &
mask;
702 int ringID = ( hitID >> 3 * word_shift ) &
mask;
703 int trtID = ( hitID >> 4 * word_shift );
706 if ( barrelElement ) {
712 ATH_MSG_WARNING(
"Could not find global coordinate of a straw - drifttime calculation will be inaccurate" );
713 return { 0., 0., 0. };
721 return (
gasType( straw_id ) == 1 );
740 ATH_MSG_WARNING(
"TRTFastDigitizationTool::gasType() getStatusHT = " <<
status <<
", must be in [1..5] range" );
751 switch( abs( particleEncoding ) ) {
773 if ( pTrk < 250. || pTrk > 7000000. )
return 0.;
780 if ( abs(
m_trt_id->
barrel_ec( straw_id ) ) == 2 ) trtPart = ( ( layerOrWheel < 6 ) ? 1 : 2 );
783 if ( trtPart == 0 ) {
784 if ( layerOrWheel )
strawLayer += 19 + ( layerOrWheel == 1 ? 0 : 24 );
786 else if ( trtPart == 1 ) {
793 const int strawLayerMax[] = { 72, 95, 63 };
799 const double hitGlobalPositionMin[] = { 0., 630., 630. };
800 const double hitGlobalPositionMax[] = { 720., 1030., 1030. };
802 if ( std::abs(hitGlobalPosition) < hitGlobalPositionMin[ trtPart ] ) {
803 ATH_MSG_WARNING(
"hitGlobalPosition was below allowed range (will be adjusted): trtPart = " << trtPart <<
", hitGlobalPosition = " << hitGlobalPosition );
804 hitGlobalPosition = copysign(hitGlobalPositionMin[ trtPart ] + 0.001,hitGlobalPosition);
806 if ( std::abs(hitGlobalPosition) > hitGlobalPositionMax[ trtPart ] ) {
807 ATH_MSG_WARNING(
"hitGlobalPosition was above allowed range (will be adjusted): trtPart = " << trtPart <<
", hitGlobalPosition = " << hitGlobalPosition );
808 hitGlobalPosition = copysign(hitGlobalPositionMax[ trtPart ] - 0.001,hitGlobalPosition);
811 if ( rTrkWire > 2.2 ) rTrkWire = 2.175;
816 if ( probHT == 0.5 || probHT == 1. ) probHT = 0.;
825 constexpr std::array< double, 14 >
bins = { 0.05, 0.15, 0.25, 0.35, 0.45, 0.55, 0.65, 0.75, 0.85, 1.05, 1.4, 1.5, 1.6, 1.82 };
826 constexpr std::array< double, 15 > probability = { 0.210,
849 constexpr std::array< double, 14 >
bins = { 0.05, 0.15, 0.25, 0.35, 0.45, 0.55, 0.65, 0.75, 0.85, 1.05, 1.4, 1.5, 1.6, 1.82 };
850 constexpr std::array< double, 15 > probability = { 0.210,
873 constexpr std::array< double, 41 >
bins = { -2.05, -1.95, -1.85, -1.75, -1.65, -1.55, -1.45, -1.35, -1.25, -1.15, -1.05, -0.95, -0.85,
874 -0.75, -0.65, -0.55, -0.45, -0.35, -0.25, -0.15, -0.05, 0.05, 0.15, 0.25, 0.35, 0.45, 0.55, 0.65,
875 0.75, 0.85, 0.95, 1.05, 1.15, 1.25, 1.35, 1.45, 1.55, 1.65, 1.75, 1.85, 1.95
878 constexpr std::array< double, 42 > probability = { 0.04466501,
928 constexpr std::array< double, 41 >
bins = { -2.05, -1.95, -1.85, -1.75, -1.65, -1.55, -1.45, -1.35, -1.25, -1.15, -1.05, -0.95, -0.85,
929 -0.75, -0.65, -0.55, -0.45, -0.35, -0.25, -0.15, -0.05, 0.05, 0.15, 0.25, 0.35, 0.45, 0.55, 0.65,
930 0.75, 0.85, 0.95, 1.05, 1.15, 1.25, 1.35, 1.45, 1.55, 1.65, 1.75, 1.85, 1.95
933 constexpr std::array< double, 42 > probability = { 0.058,
984 const double p[][ 5 ] = { { 0.478, 0.9386, 0.9325, 0.2509, 0.03232 },
985 { 0.477001, 1.02865, 1.02910, 0.185082, 0. },
986 { 0.482528, 1.03601, 1.03693, 0.182581, 0. }
989 const double &trtFitAmplitude =
p[
BEC ][ 0 ];
990 const double &trtFitMu =
p[
BEC ][ 1 ];
991 const double &trtFitR =
p[
BEC ][ 2 ];
992 const double &trtFitSigma =
p[
BEC ][ 3 ];
993 const double &trtFitConstant =
p[
BEC ][ 4 ];
995 double efficiency = trtFitAmplitude * ( erf( ( trtFitMu + trtFitR -
driftRadius ) / ( std::sqrt( 2 ) * trtFitSigma ) )
996 + erf( ( trtFitMu + trtFitR +
driftRadius ) / ( std::sqrt( 2 ) * trtFitSigma ) )
997 - erf( ( trtFitMu - trtFitR -
driftRadius ) / ( std::sqrt( 2 ) * trtFitSigma ) )
998 - erf( ( trtFitMu - trtFitR +
driftRadius ) / ( std::sqrt( 2 ) * trtFitSigma ) )
1029 const double par[][ 6 ] = { { 5.96038, 0.797671, 1.28832, -2.02763, -2.24630, 21.6857 },
1030 { 0.522755, 0.697029, -3.90787, 6.32952, 1.06347, 3.51847 }
1035 double x1 = 1. / ( x0 +
par[ j ][ 0 ] );
1046 return StatusCode::SUCCESS;