File indexing completed on 2026-04-10 07:50:32
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #include "scuda.h"
0016 #include "squad.h"
0017 #include "sphoton.h"
0018
0019 #include "STrackInfo.h"
0020 #include "SProcessHits_EPH.h"
0021 #include "spho.h"
0022 #include "srec.h"
0023 #include "ssys.h"
0024 #include "stimer.h"
0025 #include "smeta.h"
0026
0027 #include "NP.hh"
0028 #include "SPath.hh"
0029 #include "ssys.h"
0030 #include "ssolid.h"
0031 #include "SEvt.hh"
0032 #include "SLOG.hh"
0033 #include "SOpBoundaryProcess.hh"
0034 #include "CustomStatus.h"
0035
0036 #include "G4LogicalBorderSurface.hh"
0037 #include "G4Event.hh"
0038
0039 #include "U4Recorder.hh"
0040 #include "U4Engine.h"
0041 #include "U4Track.h"
0042 #include "U4StepPoint.hh"
0043 #include "U4OpBoundaryProcess.h"
0044 #include "U4OpBoundaryProcessStatus.h"
0045 #include "U4TrackStatus.h"
0046 #include "U4Random.hh"
0047
0048 #include "U4UniformRand.h"
0049 NP* U4UniformRand::UU = nullptr ;
0050
0051
0052 #include "U4Fake.h"
0053 #include "U4VolumeMaker.hh"
0054
0055 #include "U4Surface.h"
0056 #include "U4Process.h"
0057 #include "U4Touchable.h"
0058 #include "U4Simtrace.h"
0059 #include "U4Version.h"
0060
0061 #include "SCF.h"
0062 #include "U4Step.h"
0063
0064 #ifdef WITH_PMTSIM
0065 #include "PMTSim.hh"
0066 #endif
0067
0068
0069 #include "G4OpBoundaryProcess.hh"
0070 #ifdef WITH_CUSTOM4
0071 #include "C4OpBoundaryProcess.hh"
0072 #include "C4CustomART.h"
0073 #include "C4CustomART_Debug.h"
0074 #include "C4TrackInfo.h"
0075 #include "C4Pho.h"
0076
0077 #elif PMTSIM_STANDALONE
0078 #include "CustomART.h"
0079 #include "CustomART_Debug.h"
0080 #endif
0081
0082
0083 const plog::Severity U4Recorder::LEVEL = SLOG::EnvLevel("U4Recorder", "DEBUG");
0084 UName U4Recorder::SPECS = {} ;
0085
0086 const int U4Recorder::STATES = ssys::getenvint("U4Recorder_STATES",-1) ;
0087 const int U4Recorder::RERUN = ssys::getenvint("U4Recorder_RERUN",-1) ;
0088
0089 const bool U4Recorder::SEvt_NPFold_VERBOSE = ssys::getenvbool("U4Recorder__SEvt_NPFold_VERBOSE") ;
0090 const bool U4Recorder::PIDX_ENABLED = ssys::getenvbool("U4Recorder__PIDX_ENABLED") ;
0091 const bool U4Recorder::EndOfRunAction_Simtrace = ssys::getenvbool("U4Recorder__EndOfRunAction_Simtrace") ;
0092 const int U4Recorder::UseGivenVelocity_KLUDGE = ssys::getenvint(_UseGivenVelocity_KLUDGE, 0) ;
0093 const char* U4Recorder::REPLICA_NAME_SELECT = ssys::getenvvar("U4Recorder__REPLICA_NAME_SELECT", "PMT") ;
0094
0095
0096 const int U4Recorder::PIDX = ssys::getenvint("PIDX",-1) ;
0097 const int U4Recorder::EIDX = ssys::getenvint("EIDX",-1) ;
0098 const int U4Recorder::GIDX = ssys::getenvint("GIDX",-1) ;
0099
0100 std::string U4Recorder::Desc()
0101 {
0102 std::stringstream ss ;
0103 ss << _UseGivenVelocity_KLUDGE << ":" << UseGivenVelocity_KLUDGE << "\n"
0104 << U4Version::Desc()
0105 << Switches()
0106 << "\n"
0107 ;
0108 std::string str = ss.str();
0109 return str ;
0110 }
0111 std::string U4Recorder::DescFull()
0112 {
0113 std::stringstream ss ;
0114 ss << "U4Recorder::Desc" << std::endl
0115 << " U4Recorder_STATES : " << STATES << std::endl
0116 << " U4Recorder_RERUN : " << RERUN << std::endl
0117 << " U4Recorder__PIDX_ENABLED : " << ( PIDX_ENABLED ? "YES" : "NO " ) << std::endl
0118 << " U4Recorder__SEvt_NPFold_VERBOSE : " << ( SEvt_NPFold_VERBOSE ? "YES" : "NO " ) << std::endl
0119 << " U4Recorder__EndOfRunAction_Simtrace : " << ( EndOfRunAction_Simtrace ? "YES" : "NO " ) << std::endl
0120 << " U4Recorder__REPLICA_NAME_SELECT : " << ( REPLICA_NAME_SELECT ? REPLICA_NAME_SELECT : "-" ) << std::endl
0121 << " PIDX : " << PIDX << std::endl
0122 << " EIDX : " << EIDX << std::endl
0123 << " GIDX : " << GIDX << std::endl
0124 << " U4Version::Desc : " << U4Version::Desc() << "\n"
0125 ;
0126
0127 bool uoc = UserSteppingAction_Optical_ClearNumberOfInteractionLengthLeft ;
0128 ss << UserSteppingAction_Optical_ClearNumberOfInteractionLengthLeft_ << ":" << int(uoc) << std::endl ;
0129 ss << Switches() << std::endl ;
0130 std::string str = ss.str();
0131 return str ;
0132 }
0133
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143 std::string U4Recorder::Switches()
0144 {
0145 std::stringstream ss ;
0146 ss << "U4Recorder::Switches" << std::endl ;
0147 #ifdef WITH_CUSTOM4
0148 ss << "WITH_CUSTOM4" << std::endl ;
0149 #else
0150 ss << "NOT:WITH_CUSTOM4" << std::endl ;
0151 #endif
0152 #ifdef WITH_PMTSIM
0153 ss << "WITH_PMTSIM" << std::endl ;
0154 #else
0155 ss << "NOT:WITH_PMTSIM" << std::endl ;
0156 #endif
0157 #ifdef PMTSIM_STANDALONE
0158 ss << "PMTSIM_STANDALONE" << std::endl ;
0159 #else
0160 ss << "NOT:PMTSIM_STANDALONE" << std::endl ;
0161 #endif
0162
0163 #ifdef PRODUCTION
0164 ss << "PRODUCTION" << std::endl ;
0165 #else
0166 ss << "NOT:PRODUCTION" << std::endl ;
0167 #endif
0168
0169 #ifdef WITH_INSTRUMENTED_DEBUG
0170 ss << "WITH_INSTRUMENTED_DEBUG" << std::endl ;
0171 #else
0172 ss << "NOT:WITH_INSTRUMENTED_DEBUG" << std::endl ;
0173 #endif
0174
0175 std::string str = ss.str();
0176 return str ;
0177 }
0178
0179
0180
0181
0182 std::string U4Recorder::EnabledLabel()
0183 {
0184 std::stringstream ss ;
0185 if( GIDX > -1 ) ss << "GIDX_" << GIDX << "_" ;
0186 if( EIDX > -1 ) ss << "EIDX_" << EIDX << "_" ;
0187 if( GIDX == -1 && EIDX == -1 ) ss << "ALL" ;
0188 std::string s = ss.str();
0189 return s ;
0190 }
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218 bool U4Recorder::Enabled(const spho& label)
0219 {
0220 return GIDX == -1 ?
0221 ( EIDX == -1 || label.id == EIDX )
0222 :
0223 ( GIDX == -1 || label.gs == GIDX )
0224 ;
0225 }
0226
0227
0228 std::string U4Recorder::desc() const
0229 {
0230 std::stringstream ss ;
0231 ss << "U4Recorder::desc" ;
0232 std::string s = ss.str();
0233 return s ;
0234 }
0235
0236
0237
0238 U4Recorder* U4Recorder::INSTANCE = nullptr ;
0239 U4Recorder* U4Recorder::Get(){ return INSTANCE ; }
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251 U4Recorder::U4Recorder()
0252 :
0253 eventID(-1),
0254 transient_fSuspend_track(nullptr),
0255 rerun_rand(nullptr),
0256 sev(SEvt::CreateOrReuse(SEvt::ECPU)),
0257 tree(nullptr)
0258 {
0259 init();
0260 }
0261
0262 void U4Recorder::init()
0263 {
0264 INSTANCE = this ;
0265 init_SEvt();
0266 }
0267
0268 void U4Recorder::init_SEvt()
0269 {
0270 smeta::Collect(sev->meta, "U4Recorder::init_SEvt" );
0271
0272 #ifdef WITH_CUSTOM4
0273
0274 NP::SetMeta<std::string>(sev->meta, "C4Version", "TBD" ) ;
0275 #else
0276 NP::SetMeta<std::string>(sev->meta, "C4Version", "NOT-WITH_CUSTOM4" );
0277 #endif
0278
0279 NP::SetMeta<int>(sev->meta, _UseGivenVelocity_KLUDGE, UseGivenVelocity_KLUDGE );
0280 NP::SetMeta<int>(sev->meta, "G4VERSION_NUMBER", G4VERSION_NUMBER );
0281
0282 LOG(LEVEL) << " sev " << std::hex << sev << std::dec ;
0283 LOG(LEVEL) << "sev->meta[" << sev->meta << "]" ;
0284
0285 if(SEvt_NPFold_VERBOSE)
0286 {
0287 LOG(info) << " U4Recorder__SEvt_NPFold_VERBOSE : setting SEvt:setFoldVerbose " ;
0288 sev->setFoldVerbose(true);
0289 }
0290 }
0291
0292
0293
0294
0295
0296
0297
0298
0299
0300
0301
0302
0303
0304 void U4Recorder::addProcessHits_EPH(NP* eph_meta)
0305 {
0306 sev->addProcessHits_EPH(eph_meta);
0307 }
0308
0309
0310 void U4Recorder::setU4Tree(const U4Tree* _tree)
0311 {
0312 tree = _tree ;
0313 }
0314 const U4Tree* U4Recorder::getU4Tree() const
0315 {
0316 return tree ;
0317 }
0318
0319
0320
0321
0322 void U4Recorder::BeginOfRunAction(const G4Run*)
0323 {
0324 LOG(LEVEL);
0325 }
0326
0327
0328
0329
0330
0331
0332 void U4Recorder::EndOfRunAction(const G4Run*)
0333 {
0334 SEvt::SetRunMeta<int>("FAKES_SKIP", int(FAKES_SKIP) );
0335
0336
0337 LOG(LEVEL)
0338 << "[ U4Recorder__EndOfRunAction_Simtrace : " << ( EndOfRunAction_Simtrace ? "YES" : "NO " )
0339 ;
0340
0341 if(EndOfRunAction_Simtrace)
0342 {
0343 U4Simtrace::EndOfRunAction(tree) ;
0344 }
0345
0346 LOG(LEVEL)
0347 << "] U4Recorder__EndOfRunAction_Simtrace : " << ( EndOfRunAction_Simtrace ? "YES" : "NO " )
0348 ;
0349 }
0350
0351 void U4Recorder::BeginOfEventAction(const G4Event*)
0352 {
0353 LOG(fatal) << "CHANGE TO U4Recorder::BeginOfEventAction_ : see G4CXOpticks::SensitiveDetector_EndOfEvent " ;
0354 assert(0);
0355 }
0356 void U4Recorder::EndOfEventAction(const G4Event*)
0357 {
0358 LOG(fatal) << "CHANGE TO U4Recorder::EndOfEventAction_ : see G4CXOpticks::SensitiveDetector_EndOfEvent" ;
0359 assert(0);
0360 }
0361
0362
0363 void U4Recorder::BeginOfEventAction_(int eventID_)
0364 {
0365 eventID = eventID_ ;
0366 LOG(info) << " eventID " << eventID ;
0367 LOG_IF(info, SEvt::LIFECYCLE ) << " eventID " << eventID ;
0368 sev->beginOfEvent(eventID);
0369 }
0370
0371
0372
0373
0374
0375
0376
0377
0378
0379
0380 void U4Recorder::EndOfEventAction_(int eventID_)
0381 {
0382 assert( eventID == eventID_ );
0383 LOG_IF(info, SEvt::LIFECYCLE ) << " eventID " << eventID ;
0384
0385 #if defined(WITH_PMTSIM) && defined(POM_DEBUG)
0386 NP* mtda = PMTSim::ModelTrigger_Debug_Array();
0387 std::string name = mtda->get_meta<std::string>("NAME", "MTDA.npy") ;
0388 sev->add_array( name.c_str(), mtda );
0389 #else
0390 LOG(LEVEL) << "not-(WITH_PMTSIM and POM_DEBUG)" ;
0391 #endif
0392
0393
0394
0395 sev->add_array("TRS.npy", U4VolumeMaker::GetTransforms() );
0396 sev->add_array("U4R.npy", MakeMetaArray() );
0397 sev->addEventConfigArray();
0398
0399 sev->gather() ;
0400
0401
0402 sev->topfold->concat();
0403 sev->topfold->clear_subfold();
0404
0405 sev->endOfEvent(eventID_);
0406
0407 const char* savedir = sev->getSaveDir() ;
0408 LOG(LEVEL) << " savedir " << ( savedir ? savedir : "-" );
0409 SaveMeta(savedir);
0410 }
0411
0412
0413 void U4Recorder::PreUserTrackingAction(const G4Track* track){ LOG(LEVEL) ; if(U4Track::IsOptical(track)) PreUserTrackingAction_Optical(track); }
0414 void U4Recorder::PostUserTrackingAction(const G4Track* track){ LOG(LEVEL) ; if(U4Track::IsOptical(track)) PostUserTrackingAction_Optical(track); }
0415
0416 void U4Recorder::PreUserTrackingAction_(const G4Track* track, int* label){ LOG(LEVEL) ; if(U4Track::IsOptical(track)) PreUserTrackingAction_Optical_(track, label); }
0417 void U4Recorder::PostUserTrackingAction_(const G4Track* track, int* label){ LOG(LEVEL) ; if(U4Track::IsOptical(track)) PostUserTrackingAction_Optical_(track, label); }
0418
0419
0420
0421 #include "U4OpBoundaryProcess.h"
0422
0423 void U4Recorder::UserSteppingAction(const G4Step* step)
0424 {
0425 if(!U4Track::IsOptical(step->GetTrack())) return ;
0426
0427 #if defined(WITH_CUSTOM4)
0428 UserSteppingAction_Optical<C4OpBoundaryProcess>(step);
0429 #elif defined(WITH_PMTSIM)
0430 UserSteppingAction_Optical<CustomG4OpBoundaryProcess>(step);
0431 #elif defined(WITH_INSTRUMENTED_DEBUG)
0432 UserSteppingAction_Optical<InstrumentedG4OpBoundaryProcess>(step);
0433 #else
0434 UserSteppingAction_Optical<G4OpBoundaryProcess>(step);
0435 #endif
0436 }
0437
0438
0439
0440
0441
0442
0443
0444
0445
0446
0447
0448
0449
0450
0451
0452
0453
0454
0455
0456
0457
0458
0459
0460
0461
0462
0463 void U4Recorder::PreUserTrackingAction_Optical(const G4Track* track)
0464 {
0465 spho ulabel = {} ;
0466 PreUserTrackingAction_Optical_GetLabel(ulabel, track);
0467 PreUserTrackingAction_Optical_(track, ulabel.data() );
0468 }
0469
0470
0471 void U4Recorder::PreUserTrackingAction_Optical_(const G4Track* track, int* label)
0472 {
0473 LOG(LEVEL) << "[" ;
0474 if(UseGivenVelocity_KLUDGE == 1)
0475 {
0476 LOG(LEVEL) << " YES:UseGivenVelocity_KLUDGE " ;
0477 G4Track* _track = const_cast<G4Track*>(track) ;
0478 _track->UseGivenVelocity(true);
0479 }
0480 else
0481 {
0482 LOG(LEVEL) << " ASIS: without UseGivenVelocity_KLUDGE " ;
0483 }
0484
0485
0486 spho& ulabel = reinterpret_cast<spho&>(*label);
0487
0488 if(ulabel.isPlaceholder())
0489 {
0490 int track_id = U4Track::Id(track);
0491 ulabel.set_fabricated_(track_id);
0492 }
0493
0494
0495 bool skip = !Enabled(ulabel) ;
0496 LOG_IF( info, skip ) << " Enabled-SKIP EIDX/GIDX " << EIDX << "/" << GIDX ;
0497 if(skip) return ;
0498
0499 bool modulo = ulabel.id % 100000 == 0 ;
0500 LOG_IF(info, modulo) << " modulo 100000 : ulabel.id " << ulabel.id ;
0501
0502 U4Random::SetSequenceIndex(ulabel.id);
0503
0504 bool resume_fSuspend = track == transient_fSuspend_track ;
0505 G4TrackStatus tstat = track->GetTrackStatus();
0506 LOG(LEVEL)
0507 << " track " << track
0508 << " status:" << U4TrackStatus::Name(tstat)
0509 << " resume_fSuspend " << ( resume_fSuspend ? "YES" : "NO" )
0510 ;
0511 assert( tstat == fAlive );
0512
0513 SEvt* sev = SEvt::Get_ECPU();
0514 LOG_IF(fatal, sev == nullptr) << " SEvt::Get(1) returned nullptr " ;
0515 assert(sev);
0516
0517 if(ulabel.gen() == 0)
0518 {
0519 if(resume_fSuspend == false)
0520 {
0521 sev->beginPhoton(ulabel);
0522 }
0523 else
0524 {
0525 sev->resumePhoton(ulabel);
0526 }
0527 }
0528 else if( ulabel.gen() > 0 )
0529 {
0530 if(resume_fSuspend == false)
0531 {
0532 sev->rjoinPhoton(ulabel);
0533 }
0534 else
0535 {
0536 sev->rjoin_resumePhoton(ulabel);
0537 }
0538 }
0539 LOG(LEVEL) << "]" ;
0540
0541 }
0542
0543
0544
0545
0546
0547
0548
0549
0550
0551
0552
0553
0554
0555
0556
0557
0558
0559
0560
0561
0562
0563
0564
0565
0566
0567
0568
0569
0570
0571 void U4Recorder::PreUserTrackingAction_Optical_GetLabel( spho& ulabel, const G4Track* track )
0572 {
0573 #ifdef WITH_CUSTOM4_OLD
0574 C4Pho* label = C4TrackInfo<C4Pho>::GetRef(track);
0575 #elif WITH_CUSTOM4
0576 C4Pho* label = C4TrackInfo::GetRef(track);
0577 #else
0578 spho* label = STrackInfo::GetRef(track);
0579 #endif
0580
0581 if( label == nullptr )
0582 {
0583 PreUserTrackingAction_Optical_FabricateLabel(track) ;
0584 #ifdef WITH_CUSTOM4_OLD
0585 label = C4TrackInfo<C4Pho>::GetRef(track);
0586 #elif WITH_CUSTOM4
0587 label = C4TrackInfo::GetRef(track);
0588 #else
0589 label = STrackInfo::GetRef(track);
0590 #endif
0591 }
0592 assert( label && label->isDefined() );
0593
0594 #ifdef WITH_CUSTOM4
0595 assert( C4Pho::N == spho::N );
0596 #endif
0597 std::array<int,spho::N> a_label ;
0598 label->serialize(a_label) ;
0599
0600 ulabel.load(a_label);
0601
0602
0603
0604 }
0605
0606 void U4Recorder::PreUserTrackingAction_Optical_FabricateLabel( const G4Track* track )
0607 {
0608 int rerun_id = SEventConfig::G4StateRerun() ;
0609 if( rerun_id > -1 )
0610 {
0611 LOG(LEVEL) << " setting rerun_id " << rerun_id ;
0612 G4Track* _track = const_cast<G4Track*>(track) ;
0613 U4Track::SetId(_track, rerun_id) ;
0614 }
0615
0616 #ifdef WITH_CUSTOM4
0617 U4Track::SetFabricatedLabel(track);
0618 #else
0619 U4Track::SetFabricatedLabel(track);
0620 #endif
0621
0622 #ifdef WITH_CUSTOM4_OLD
0623 C4Pho* label = C4TrackInfo<C4Pho>::GetRef(track);
0624 #elif WITH_CUSTOM4
0625 C4Pho* label = C4TrackInfo::GetRef(track);
0626 #else
0627 spho* label = STrackInfo::GetRef(track);
0628 #endif
0629 assert(label) ;
0630
0631 LOG(LEVEL)
0632 << " labelling photon :"
0633 << " track " << track
0634 << " label " << label
0635 << " label.desc " << label->desc()
0636 ;
0637
0638 saveOrLoadStates(label->id);
0639 }
0640
0641
0642 void U4Recorder::PreUserTrackingAction_Optical_FabricateLabel_( const G4Track* track, int* label )
0643 {
0644 spho& q = reinterpret_cast<spho&>(*label) ;
0645 if(q.isPlaceholder())
0646 {
0647 int track_id = U4Track::Id(track);
0648 q.set_fabricated_(track_id);
0649 }
0650 }
0651
0652
0653
0654
0655
0656
0657
0658
0659
0660
0661
0662 void U4Recorder::GetLabel( spho& ulabel, const G4Track* track )
0663 {
0664 #ifdef WITH_CUSTOM4_OLD
0665 C4Pho* label = C4TrackInfo<C4Pho>::GetRef(track);
0666 #elif WITH_CUSTOM4
0667 C4Pho* label = C4TrackInfo::GetRef(track);
0668 #else
0669 spho* label = STrackInfo::GetRef(track);
0670 #endif
0671 assert( label && label->isDefined() && "all photons are expected to be labelled" );
0672
0673 #ifdef WITH_CUSTOM4
0674 assert( C4Pho::N == spho::N );
0675 #endif
0676 std::array<int,spho::N> a_label ;
0677 label->serialize(a_label) ;
0678
0679 ulabel.load(a_label);
0680 }
0681
0682
0683
0684
0685
0686
0687
0688
0689
0690
0691
0692
0693
0694
0695
0696
0697
0698
0699
0700
0701
0702
0703 void U4Recorder::saveOrLoadStates( int id )
0704 {
0705 bool first_event = eventID == 0 ;
0706 LOG_IF(LEVEL, !first_event ) << " skip as not first_event eventID " << eventID ;
0707 if(!first_event) return ;
0708
0709 bool g4state_save = SEventConfig::IsRunningModeG4StateSave() ;
0710 bool g4state_rerun = SEventConfig::IsRunningModeG4StateRerun() ;
0711 bool g4state_active = g4state_save || g4state_rerun ;
0712 if( g4state_active == false ) return ;
0713
0714 SEvt* sev = SEvt::Get_ECPU();
0715
0716 if(g4state_save)
0717 {
0718 NP* g4state = sev->gatherG4State();
0719 LOG_IF( fatal, g4state == nullptr ) << " cannot U4Engine::SaveState with null g4state " ;
0720 assert( g4state );
0721
0722 int max_state = g4state ? g4state->shape[0] : 0 ;
0723
0724 if( id == SEventConfig::_G4StateRerun )
0725 {
0726 LOG(LEVEL)
0727 << "U4Engine::SaveState for id (SEventConfig::_G4StateRerun) " << id
0728 << " from the max_state " << max_state
0729 << std::endl
0730 << U4Engine::DescStateArray()
0731 ;
0732 }
0733 U4Engine::SaveState( g4state, id );
0734 }
0735 else if(g4state_rerun)
0736 {
0737 const NP* g4state = sev->getG4State();
0738 LOG_IF( fatal, g4state == nullptr ) << " cannot U4Engine::RestoreState with null g4state " ;
0739 assert( g4state );
0740
0741 U4Engine::RestoreState( g4state, id );
0742
0743
0744 if( id == SEventConfig::_G4StateRerun )
0745 {
0746 rerun_rand = U4UniformRand::Get(1000);
0747 U4UniformRand::UU = rerun_rand ;
0748 SEvt::UU = rerun_rand ;
0749
0750 LOG(LEVEL)
0751 << "U4Engine::RestoreState for id (SEventConfig::_G4StateRerun) " << id
0752 << std::endl
0753 << U4Engine::DescStateArray()
0754 << std::endl
0755 << " rerun_rand (about to be consumed, did RestoreState after collecting them) "
0756 << std::endl
0757 << rerun_rand->repr<double>()
0758 << std::endl
0759 ;
0760
0761 U4Engine::RestoreState( g4state, id );
0762 }
0763 }
0764 }
0765
0766
0767
0768
0769
0770
0771
0772
0773
0774
0775 void U4Recorder::saveRerunRand(const char* dir) const
0776 {
0777 if( rerun_rand == nullptr ) return ;
0778
0779 int id = SEventConfig::_G4StateRerun ;
0780 std::string name = U::FormName("U4Recorder_G4StateRerun_", id, ".npy" );
0781 rerun_rand->save( dir, name.c_str());
0782 }
0783
0784
0785
0786
0787
0788
0789
0790
0791
0792
0793
0794
0795
0796
0797
0798
0799
0800
0801
0802
0803
0804
0805
0806 void U4Recorder::SaveMeta(const char* savedir)
0807 {
0808 if(savedir == nullptr) return ;
0809
0810 assert(INSTANCE);
0811 INSTANCE->saveRerunRand(savedir);
0812 }
0813
0814
0815 NP* U4Recorder::MakeMetaArray()
0816 {
0817 std::string descfakes = U4Recorder::DescFakes() ;
0818 LOG(LEVEL) << descfakes ;
0819
0820 NP* u4r = NP::Make<int>(1) ;
0821 u4r->fill(0) ;
0822 u4r->set_names(U4Recorder::SPECS.names);
0823 u4r->set_meta<std::string>("DescFakes", descfakes );
0824
0825 return u4r ;
0826 }
0827
0828
0829
0830
0831
0832
0833
0834 void U4Recorder::PostUserTrackingAction_Optical(const G4Track* track)
0835 {
0836 spho ulabel = {} ;
0837 GetLabel(ulabel, track);
0838 PostUserTrackingAction_Optical_(track, ulabel.data());
0839 }
0840
0841 void U4Recorder::PostUserTrackingAction_Optical_(const G4Track* track, int* label)
0842 {
0843 spho& ulabel = reinterpret_cast<spho&>(*label);
0844 if(!Enabled(ulabel)) return ;
0845
0846 G4TrackStatus tstat = track->GetTrackStatus();
0847 LOG(LEVEL) << U4TrackStatus::Name(tstat) ;
0848
0849 bool is_fStopAndKill = tstat == fStopAndKill ;
0850 bool is_fSuspend = tstat == fSuspend ;
0851 bool is_fStopAndKill_or_fSuspend = is_fStopAndKill || is_fSuspend ;
0852 LOG_IF(info, !is_fStopAndKill_or_fSuspend ) << " not is_fStopAndKill_or_fSuspend post.tstat " << U4TrackStatus::Name(tstat) ;
0853 assert( is_fStopAndKill_or_fSuspend );
0854
0855
0856 if(is_fStopAndKill)
0857 {
0858 SEvt* sev = SEvt::Get_ECPU();
0859 U4Random::SetSequenceIndex(-1);
0860 sev->finalPhoton(ulabel);
0861 transient_fSuspend_track = nullptr ;
0862 #ifndef PRODUCTION
0863 bool PIDX_DUMP = ulabel.id == PIDX && PIDX_ENABLED ;
0864 sseq& seq = sev->current_ctx.seq ;
0865
0866 LOG_IF(info, PIDX_DUMP )
0867 << " l.id " << std::setw(5) << ulabel.id
0868 << " seq " << seq.brief()
0869 ;
0870
0871 if(PIDX_DUMP) std::cerr
0872 << "U4Recorder::PostUserTrackingAction_Optical.fStopAndKill "
0873 << " ulabel.id " << std::setw(6) << ulabel.id
0874 << " seq.brief " << seq.brief()
0875 << std::endl
0876 ;
0877 #endif
0878 }
0879 else if(is_fSuspend)
0880 {
0881 transient_fSuspend_track = track ;
0882 }
0883 LOG(LEVEL) << "]" ;
0884 }
0885
0886
0887
0888
0889
0890
0891
0892
0893
0894
0895
0896
0897
0898
0899
0900
0901
0902
0903
0904
0905
0906
0907
0908
0909
0910
0911
0912
0913
0914
0915
0916
0917
0918
0919
0920
0921
0922
0923
0924
0925
0926
0927
0928
0929
0930
0931
0932
0933
0934
0935
0936
0937
0938
0939
0940
0941
0942
0943
0944
0945
0946
0947
0948
0949
0950
0951
0952
0953
0954
0955
0956
0957
0958
0959
0960
0961
0962
0963
0964
0965
0966
0967
0968
0969
0970
0971
0972
0973
0974
0975
0976
0977
0978
0979
0980
0981
0982
0983
0984
0985
0986
0987
0988
0989
0990
0991
0992
0993
0994
0995
0996
0997
0998
0999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013 template <typename T>
1014 void U4Recorder::UserSteppingAction_Optical(const G4Step* step)
1015 {
1016 const G4Track* track = step->GetTrack();
1017 G4VPhysicalVolume* pv = track->GetVolume() ;
1018 const G4VTouchable* touch = track->GetTouchable();
1019
1020 LOG(LEVEL) << "[ pv " << ( pv ? pv->GetName() : "-" ) ;
1021
1022 spho ulabel = {} ;
1023 GetLabel( ulabel, track );
1024 if(!Enabled(ulabel)) return ;
1025
1026 const G4StepPoint* pre = step->GetPreStepPoint() ;
1027 const G4StepPoint* post = step->GetPostStepPoint() ;
1028
1029 G4ThreeVector delta = step->GetDeltaPosition();
1030 double step_mm = delta.mag()/mm ;
1031
1032 SEvt* sev = SEvt::Get_ECPU();
1033 sev->checkPhotonLineage(ulabel);
1034
1035 sphoton& current_photon = sev->current_ctx.p ;
1036
1037 #ifndef PRODUCTION
1038 quad4& current_aux = sev->current_ctx.aux ;
1039 current_aux.zero_v(3, 3);
1040 #endif
1041
1042
1043 bool first_flag = current_photon.flagmask_count() == 1 ;
1044 if(first_flag)
1045 {
1046 LOG(LEVEL) << " first_flag, track " << track ;
1047 U4StepPoint::Update(current_photon, pre);
1048 #ifndef PRODUCTION
1049 current_aux.q1.i.w = int('F') ;
1050 #endif
1051 sev->pointPhoton(ulabel);
1052 }
1053
1054 bool warn = true ;
1055 bool is_tir = false ;
1056 unsigned flag = U4StepPoint::Flag<T>(post, warn, is_tir ) ;
1057
1058 bool is_fastsim_flag = flag == DEFER_FSTRACKINFO ;
1059 bool is_boundary_flag = OpticksPhoton::IsBoundaryFlag(flag) ;
1060 bool is_surface_flag = OpticksPhoton::IsSurfaceDetectOrAbsorbFlag(flag) ;
1061 bool is_detect_flag = OpticksPhoton::IsDetectFlag(flag) ;
1062
1063
1064 #ifndef PRODUCTION
1065 if(is_boundary_flag) CollectBoundaryAux<T>(¤t_aux) ;
1066 #endif
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078 unsigned iindex = is_detect_flag ?
1079 U4Touchable::ImmediateReplicaNumber(touch)
1080 :
1081 U4Touchable::AncestorReplicaNumber(touch)
1082 ;
1083
1084 current_photon.set_iindex__( iindex );
1085
1086
1087 LOG(LEVEL)
1088 << " flag " << flag
1089 << " " << OpticksPhoton::Flag(flag)
1090 << " is_tir " << is_tir
1091 << " is_fastsim_flag " << is_fastsim_flag
1092 << " is_boundary_flag " << is_boundary_flag
1093 << " is_surface_flag " << is_surface_flag
1094 ;
1095
1096
1097
1098
1099
1100
1101
1102 if(is_fastsim_flag)
1103 {
1104 char fstrackinfo_stat = ulabel.uc4.w ;
1105
1106
1107
1108 switch(fstrackinfo_stat)
1109 {
1110 case 'T': flag = BOUNDARY_TRANSMIT ; break ;
1111 case 'R': flag = BOUNDARY_REFLECT ; break ;
1112 case 'A': flag = SURFACE_ABSORB ; break ;
1113 case 'D': flag = SURFACE_DETECT ; break ;
1114 case '_': flag = 0 ; break ;
1115 default: flag = 0 ; break ;
1116 }
1117 LOG_IF(error, flag == 0)
1118 << " DEFER_FSTRACKINFO "
1119 << " FAILED TO GET THE FastSim status from trackinfo "
1120 << " fstrackinfo_stat " << fstrackinfo_stat
1121 << " fstrackinfo_stat == '\0' " << ( fstrackinfo_stat == '\0' ? "YES" : "NO " )
1122 ;
1123
1124 LOG(LEVEL)
1125 << " DEFER_FSTRACKINFO "
1126 << " fstrackinfo_stat " << fstrackinfo_stat
1127 << " flag " << OpticksPhoton::Flag(flag)
1128 ;
1129 }
1130
1131 LOG_IF(error, flag == 0)
1132 << " ERR flag zero : post "
1133 << std::endl
1134 << "U4StepPoint::DescPositionTime(post)"
1135 << std::endl
1136 << U4StepPoint::DescPositionTime(post)
1137 << std::endl
1138 << "U4StepPoint::Desc<T>(post)"
1139 << std::endl
1140 << U4StepPoint::Desc<T>(post)
1141 ;
1142
1143 assert( flag > 0 );
1144
1145 bool PIDX_DUMP = ulabel.id == PIDX && PIDX_ENABLED ;
1146 bool is_fake = false ;
1147 unsigned fakemask = 0 ;
1148 double fake_duration(-2.);
1149
1150 int st = -2 ;
1151
1152 if(FAKES_SKIP && ( flag == BOUNDARY_TRANSMIT || flag == BOUNDARY_REFLECT ) )
1153 {
1154
1155
1156 std::string spec_ = U4Step::Spec(step) ;
1157 const char* spec = spec_.c_str();
1158 fakemask = ClassifyFake(step, flag, spec, PIDX_DUMP, &fake_duration ) ;
1159 is_fake = fakemask > 0 ;
1160 st = ( is_fake ? -1 : 1 )*SPECS.add(spec, false ) ;
1161 }
1162
1163
1164 if(PIDX_DUMP)
1165 {
1166 std::cout
1167 << "U4Recorder::UserSteppingAction_Optical"
1168 << " PIDX " << PIDX
1169 << " post " << U4StepPoint::DescPositionTime(post)
1170 << " is_fastsim_flag " << is_fastsim_flag
1171 << " FAKES_SKIP " << FAKES_SKIP
1172 << " is_fake " << is_fake
1173 << " fakemask " << fakemask
1174 << std::endl
1175 ;
1176 LOG(LEVEL) << U4StepPoint::DescPositionTime(post) ;
1177 }
1178
1179
1180
1181 #ifndef PRODUCTION
1182
1183
1184
1185 current_aux.q2.i.z = fakemask ;
1186 current_aux.q2.f.w = float(fake_duration) ;
1187 #endif
1188
1189
1190
1191 bool slow_fake = fake_duration > SLOW_FAKE ;
1192
1193 LOG_IF(info, PIDX_DUMP || slow_fake )
1194 << " l.id " << std::setw(3) << ulabel.id
1195 << " step_mm " << std::fixed << std::setw(10) << std::setprecision(4) << step_mm
1196 << " abbrev " << OpticksPhoton::Abbrev(flag)
1197 << " st " << std::setw(3) << st
1198 << " is_fake " << ( is_fake ? "YES" : "NO " )
1199 << " fakemask " << fakemask
1200 << " fake_duration " << fake_duration
1201 << " slow_fake " << slow_fake
1202 << " SLOW_FAKE " << SLOW_FAKE
1203 << " U4Fake::Desc " << U4Fake::Desc(fakemask)
1204 ;
1205
1206 if( flag == NAN_ABORT )
1207 {
1208 LOG(LEVEL) << " skip post saving for StepTooSmall ulabel.id " << ulabel.id ;
1209 }
1210 else if( FAKES_SKIP && is_fake )
1211 {
1212 LOG(LEVEL) << " FAKES_SKIP skip post identified as fake ulabel.id " << ulabel.id ;
1213 }
1214 else
1215 {
1216 G4TrackStatus tstat = track->GetTrackStatus();
1217
1218 Check_TrackStatus_Flag(tstat, flag, "UserSteppingAction_Optical" );
1219
1220 U4StepPoint::Update(current_photon, post);
1221
1222
1223
1224 unsigned eph = ulabel.eph();
1225 if( flag == SURFACE_DETECT || flag == SURFACE_ABSORB || flag == BULK_ABSORB )
1226 {
1227 EPH_FlagCheck(flag,eph);
1228 }
1229 if( flag == SURFACE_DETECT )
1230 {
1231 flag = EPH_EFFICIENCY_COLLECT_OR_CULL( eph );
1232 LOG_IF(info, SEvt::EPH_) << "changed SD flag to " << OpticksPhoton::Abbrev(flag) << " due to eph " << EPH::Name(eph) ;
1233 }
1234
1235
1236 current_photon.set_flag( flag );
1237
1238 if(U4Step::CF) U4Step::MockOpticksBoundaryIdentity(current_photon, step, ulabel.id );
1239
1240 sev->pointPhoton(ulabel);
1241 }
1242
1243 if(UserSteppingAction_Optical_ClearNumberOfInteractionLengthLeft)
1244 {
1245 U4Process::ClearNumberOfInteractionLengthLeft(*track, *step);
1246 }
1247
1248 LOG(LEVEL) << "]" ;
1249 }
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269 unsigned U4Recorder::EPH_EFFICIENCY_COLLECT_OR_CULL(unsigned eph)
1270 {
1271 bool eph_collect = eph == EPH::SAVENORM || eph == EPH::YMERGE ;
1272 bool eph_cull = eph == EPH::NDECULL ;
1273 assert( eph_collect ^ eph_cull ) ;
1274 return eph_collect ? EFFICIENCY_COLLECT : EFFICIENCY_CULL ;
1275 }
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306 void U4Recorder::EPH_FlagCheck(unsigned original_flag, unsigned eph)
1307 {
1308 bool expected_original_flag = original_flag == SURFACE_DETECT || original_flag == SURFACE_ABSORB || original_flag == BULK_ABSORB ;
1309
1310 bool is_eph_surface_absorb = eph == EPH::NEDEP || eph == EPH::UNSET ;
1311 bool is_eph_bulk_absorb = eph == EPH::NEDEP || eph == EPH::UNSET || eph == EPH::NBOUND ;
1312 bool is_eph_collect = eph == EPH::SAVENORM || eph == EPH::YMERGE ;
1313 bool is_eph_cull = eph == EPH::NDECULL ;
1314 bool is_eph_detect = eph == EPH::SAVENORM || eph == EPH::YMERGE || eph == EPH::NDECULL ;
1315
1316 bool consistent_flag = ( original_flag == SURFACE_DETECT && is_eph_detect ) ||
1317 ( original_flag == SURFACE_ABSORB && is_eph_surface_absorb ) ||
1318 ( original_flag == BULK_ABSORB && is_eph_bulk_absorb ) ;
1319
1320 bool surprise_flag = ( original_flag == SURFACE_ABSORB && is_eph_cull );
1321
1322
1323 LOG_IF(info, !consistent_flag || !expected_original_flag )
1324 << " original_flag " << OpticksPhoton::Flag(original_flag)
1325 << " expected_original_flag " << ( expected_original_flag ? "YES" : "NO " )
1326 << " eph " << std::setw(2) << eph
1327 << " eph_ " << EPH::Name(eph)
1328 << " is_eph_collect " << ( is_eph_collect ? "YES" : "NO " )
1329 << " is_eph_cull " << ( is_eph_cull ? "YES" : "NO " )
1330 << " consistent_flag " << ( consistent_flag ? "YES" : "NO " )
1331 << " surpise_flag " << ( surprise_flag ? "YES" : "NO" )
1332 ;
1333
1334 assert( consistent_flag || surprise_flag );
1335 assert( expected_original_flag );
1336 }
1337
1338
1339
1340
1341
1342
1343
1344 const double U4Recorder::SLOW_FAKE = ssys::getenvdouble("U4Recorder__SLOW_FAKE", 1e-2) ;
1345 const bool U4Recorder::UserSteppingAction_Optical_ClearNumberOfInteractionLengthLeft = ssys::getenvbool(UserSteppingAction_Optical_ClearNumberOfInteractionLengthLeft_) ;
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365 template <typename T>
1366 void U4Recorder::CollectBoundaryAux(quad4* )
1367 {
1368 LOG(LEVEL) << "generic do nothing" ;
1369 }
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386 #if defined(WITH_CUSTOM4)
1387 template<>
1388 void U4Recorder::CollectBoundaryAux<C4OpBoundaryProcess>(quad4* current_aux)
1389 {
1390 C4OpBoundaryProcess* bop = U4OpBoundaryProcess::Get<C4OpBoundaryProcess>() ;
1391 assert(bop) ;
1392 assert(current_aux);
1393
1394 char customStatus = bop ? bop->m_custom_status : 'B' ;
1395 C4CustomART* cart = bop ? bop->m_custom_art : nullptr ;
1396 const double* recoveredNormal = bop ? (const double*)&(bop->theRecoveredNormal) : nullptr ;
1397
1398 #ifdef C4_DEBUG
1399 C4CustomART_Debug* cdbg = cart ? &(cart->dbg) : nullptr ;
1400 #else
1401 C4CustomART_Debug* cdbg = nullptr ;
1402 #endif
1403
1404 LOG(LEVEL)
1405 << " bop " << ( bop ? "Y" : "N" )
1406 << " cart " << ( cart ? "Y" : "N" )
1407 << " cdbg " << ( cdbg ? "Y" : "N" )
1408 << " current_aux " << ( current_aux ? "Y" : "N" )
1409 << " bop.m_custom_status " << customStatus
1410 << " CustomStatus::Name " << CustomStatus::Name(customStatus)
1411 ;
1412
1413 if(cdbg && customStatus == 'Y') current_aux->load( cdbg->data(), C4CustomART_Debug::N ) ;
1414 current_aux->set_v(3, recoveredNormal, 3);
1415 current_aux->q3.i.w = int(customStatus) ;
1416 }
1417
1418 #elif defined(WITH_PMTSIM) || defined(WITH_CUSTOM_BOUNDARY)
1419
1420
1421
1422 template<>
1423 void U4Recorder::CollectBoundaryAux<CustomG4OpBoundaryProcess>(quad4* current_aux)
1424 {
1425 CustomG4OpBoundaryProcess* bop = U4OpBoundaryProcess::Get<CustomG4OpBoundaryProcess>() ;
1426 assert(bop) ;
1427
1428 char customStatus = bop ? bop->m_custom_status : 'B' ;
1429 CustomART* cart = bop ? bop->m_custom_art : nullptr ;
1430 const double* recoveredNormal = bop ? (const double*)&(bop->theRecoveredNormal) : nullptr ;
1431 CustomART_Debug* cdbg = cart ? &(cart->dbg) : nullptr ;
1432
1433 LOG(LEVEL)
1434 << " bop " << ( bop ? "Y" : "N" )
1435 << " cart " << ( cart ? "Y" : "N" )
1436 << " cdbg " << ( cdbg ? "Y" : "N" )
1437 << " current_aux " << ( current_aux ? "Y" : "N" )
1438 << " bop.m_custom_status " << customStatus
1439 << " CustomStatus::Name " << CustomStatus::Name(customStatus)
1440 ;
1441
1442 assert( current_aux );
1443 if(cdbg && customStatus == 'Y')
1444 {
1445
1446
1447
1448 current_aux->q0.f.x = cdbg->A ;
1449 current_aux->q0.f.y = cdbg->R ;
1450 current_aux->q0.f.z = cdbg->T ;
1451 current_aux->q0.f.w = cdbg->_qe ;
1452
1453 current_aux->q1.f.x = cdbg->An ;
1454 current_aux->q1.f.y = cdbg->Rn ;
1455 current_aux->q1.f.z = cdbg->Tn ;
1456 current_aux->q1.f.w = cdbg->escape_fac ;
1457
1458 current_aux->q2.f.x = cdbg->minus_cos_theta ;
1459 current_aux->q2.f.y = cdbg->wavelength_nm ;
1460 current_aux->q2.f.z = cdbg->pmtid ;
1461 current_aux->q2.f.w = -1. ;
1462 }
1463
1464 current_aux->set_v(3, recoveredNormal, 3);
1465 current_aux->q3.i.w = int(customStatus) ;
1466 }
1467 #endif
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526 const double U4Recorder::EPSILON = 1e-4 ;
1527 const bool U4Recorder::ClassifyFake_FindPV_r = ssys::getenvbool("U4Recorder__ClassifyFake_FindPV_r" );
1528 stimer* U4Recorder::TIMER = new stimer ;
1529
1530 unsigned U4Recorder::ClassifyFake(const G4Step* step, unsigned flag, const char* spec, bool dump, double* duration )
1531 {
1532 if(duration) TIMER->start() ;
1533
1534 unsigned fakemask = 0 ;
1535 G4ThreeVector delta = step->GetDeltaPosition();
1536 double step_mm = delta.mag()/mm ;
1537
1538
1539 bool is_reflect_flag = OpticksPhoton::IsReflectFlag(flag);
1540 bool is_small_step = step_mm < EPSILON && is_reflect_flag == false ;
1541 bool is_vacvac_inner1_inner2 = U4Step::IsSameMaterialPVBorder(step, "Vacuum", "inner1_phys", "inner2_phys") ;
1542
1543 if(is_small_step) fakemask |= U4Fake::FAKE_STEP_MM ;
1544 if(is_vacvac_inner1_inner2) fakemask |= U4Fake::FAKE_VV_INNER12 ;
1545 if(IsListedFake(spec)) fakemask |= U4Fake::FAKE_MANUAL ;
1546
1547
1548
1549
1550 const char* fake_pv_name = "body_phys" ;
1551 const G4Track* track = step->GetTrack();
1552 const G4VTouchable* touch = track->GetTouchable();
1553 const G4VPhysicalVolume* pv = track->GetVolume() ;
1554 const char* pv_name = pv->GetName().c_str();
1555 bool pv_name_proceed =
1556 strstr(pv_name, "PMT") != nullptr ||
1557 strstr(pv_name, "nnvt") != nullptr ||
1558 strstr(pv_name, "hama") != nullptr
1559 ;
1560
1561
1562 const G4VPhysicalVolume* fpv = U4Touchable::FindPV(touch, fake_pv_name, U4Touchable::MATCH_END );
1563 int maxdepth = 2 ;
1564
1565 if( fpv == nullptr && ClassifyFake_FindPV_r && pv_name_proceed )
1566 {
1567 fpv = U4Volume::FindPV( pv, fake_pv_name, sstr::MATCH_END, maxdepth );
1568 }
1569
1570
1571
1572 if(dump && fpv == nullptr) std::cout
1573 << "U4Recorder::ClassifyFake"
1574 << " fpv null "
1575 << " pv_name " << ( pv_name ? pv_name : "-" )
1576 << " pv_name_proceed " << ( pv_name_proceed ? "YES" : "NO ")
1577 << " ClassifyFake_FindPV_r " << ( ClassifyFake_FindPV_r ? "YES" : "NO " )
1578 << U4Touchable::Desc(touch)
1579 << U4Touchable::Brief(touch)
1580 << std::endl
1581 ;
1582
1583 G4LogicalVolume* flv = fpv ? fpv->GetLogicalVolume() : nullptr ;
1584 G4VSolid* fso = flv ? flv->GetSolid() : nullptr ;
1585
1586 const G4AffineTransform& transform = touch->GetHistory()->GetTopTransform();
1587 const G4StepPoint* post = step->GetPostStepPoint() ;
1588 const G4ThreeVector& theGlobalPoint = post->GetPosition();
1589 const G4ThreeVector& theGlobalDirection = post->GetMomentumDirection() ;
1590
1591 G4ThreeVector theLocalPoint = transform.TransformPoint(theGlobalPoint);
1592 G4ThreeVector theLocalDirection = transform.TransformAxis(theGlobalDirection);
1593 G4ThreeVector theLocalIntersect(0.,0.,0.) ;
1594
1595 EInside fin = kOutside ;
1596 G4double fdist = fso == nullptr ? kInfinity : ssolid::Distance_( fso, theLocalPoint, theLocalDirection, fin, &theLocalIntersect ) ;
1597
1598
1599 if(fdist < EPSILON) fakemask |= U4Fake::FAKE_FDIST ;
1600 if(fin == kSurface) fakemask |= U4Fake::FAKE_SURFACE ;
1601
1602 if(duration) *duration = TIMER->done() ;
1603
1604
1605 if(dump) std::cout
1606 << "U4Recorder::ClassifyFake"
1607 << " fdist " << ( fdist == kInfinity ? -1. : fdist )
1608 << " fin " << sgeomdefs::EInside_(fin)
1609 << " fso " << ( fso ? fso->GetName() : "-" )
1610 << " theLocalPoint " << theLocalPoint
1611 << " theLocalDirection " << theLocalDirection
1612 << " theLocalIntersect " << theLocalIntersect
1613 << " fakemask " << fakemask
1614 << " desc " << U4Fake::Desc(fakemask)
1615 << " duration " << std::scientific << ( duration ? *duration : -1. )
1616 << std::endl
1617 ;
1618
1619 return fakemask ;
1620 }
1621
1622
1623 std::vector<std::string>* U4Recorder::FAKES = ssys::getenv_vec<std::string>("U4Recorder__FAKES", "" );
1624 bool U4Recorder::FAKES_SKIP = ssys::getenvbool( "U4Recorder__FAKES_SKIP") ;
1625
1626 bool U4Recorder::IsListedFake( const char* spec ){ return ssys::is_listed(FAKES, spec ) ; }
1627
1628 std::string U4Recorder::DescFakes()
1629 {
1630 std::stringstream ss ;
1631 ss << "U4Recorder::DescFakes " << std::endl
1632 << "U4Recorder::FAKES_SKIP " << ( FAKES_SKIP ? "YES" : "NO " ) << std::endl
1633 << "U4Recorder::FAKES " << ( FAKES ? "YES" : "NO " ) << std::endl
1634 << "FAKES.size " << ( FAKES ? FAKES->size() : -1 ) << std::endl
1635 ;
1636
1637 if(FAKES) for(int i=0 ; i < int(FAKES->size()) ; i++) ss << (*FAKES)[i] << std::endl ;
1638 std::string str = ss.str();
1639 return str ;
1640 }
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650 void U4Recorder::Check_TrackStatus_Flag(G4TrackStatus tstat, unsigned flag, const char* from )
1651 {
1652 LOG(LEVEL) << " step.tstat " << U4TrackStatus::Name(tstat) << " " << OpticksPhoton::Flag(flag) << " from " << from ;
1653
1654 if( tstat == fAlive )
1655 {
1656 bool is_live_flag = OpticksPhoton::IsLiveFlag(flag);
1657 LOG_IF(error, !is_live_flag )
1658 << " is_live_flag " << is_live_flag
1659 << " unexpected trackStatus/flag "
1660 << " trackStatus " << U4TrackStatus::Name(tstat)
1661 << " flag " << OpticksPhoton::Flag(flag)
1662 ;
1663
1664
1665 }
1666 else if( tstat == fSuspend )
1667 {
1668 LOG(LEVEL) << " fSuspend : this happens when hand over to FastSim, ie when ModelTrigger:YES " ;
1669 }
1670 else if( tstat == fStopAndKill )
1671 {
1672 bool is_terminal_flag = OpticksPhoton::IsTerminalFlag(flag);
1673 LOG_IF(error, !is_terminal_flag )
1674 << " is_terminal_flag " << is_terminal_flag
1675 << " unexpected trackStatus/flag "
1676 << " trackStatus " << U4TrackStatus::Name(tstat)
1677 << " flag " << OpticksPhoton::Flag(flag)
1678 ;
1679 assert( is_terminal_flag );
1680 }
1681 else
1682 {
1683 LOG(fatal)
1684 << " unexpected trackstatus "
1685 << " trackStatus " << U4TrackStatus::Name(tstat)
1686 << " flag " << OpticksPhoton::Flag(flag)
1687 ;
1688 }
1689 }
1690
1691
1692
1693 #if defined(WITH_CUSTOM4)
1694 #include "C4OpBoundaryProcess.hh"
1695 template void U4Recorder::UserSteppingAction_Optical<C4OpBoundaryProcess>(const G4Step*) ;
1696 #elif defined(WITH_PMTSIM)
1697 #include "CustomG4OpBoundaryProcess.hh"
1698 template void U4Recorder::UserSteppingAction_Optical<CustomG4OpBoundaryProcess>(const G4Step*) ;
1699 #elif defined(WITH_INSTRUMENTED_DEBUG)
1700 #include "InstrumentedG4OpBoundaryProcess.hh"
1701 template void U4Recorder::UserSteppingAction_Optical<InstrumentedG4OpBoundaryProcess>(const G4Step*) ;
1702 #else
1703 #include "G4OpBoundaryProcess.hh"
1704 template void U4Recorder::UserSteppingAction_Optical<G4OpBoundaryProcess>(const G4Step*) ;
1705 #endif
1706
1707