File indexing completed on 2026-04-10 07:50:32
0001 #include <iostream>
0002 #include <iomanip>
0003 #include <sstream>
0004 #include <cstdlib>
0005 #include <csignal>
0006
0007 #include "Randomize.hh"
0008 #include "G4Types.hh"
0009 #include "U4Random.hh"
0010 #include "U4Stack.h"
0011 #include "U4StackAuto.h"
0012
0013 #include "NP.hh"
0014 #include "spath.h"
0015 #include "ssys.h"
0016
0017 #include "SEvt.hh"
0018 #include "SBacktrace.h"
0019 #include "SDBG.h"
0020
0021 #include "SLOG.hh"
0022
0023 const plog::Severity U4Random::LEVEL = SLOG::EnvLevel("U4Random", "DEBUG") ;
0024
0025 U4Random* U4Random::INSTANCE = nullptr ;
0026 U4Random* U4Random::Get(){ return INSTANCE ; }
0027
0028 const char* U4Random::NAME = "U4Random" ;
0029
0030
0031 void U4Random::SetSequenceIndex(int index)
0032 {
0033 if(U4Random::Get() == nullptr) return ;
0034
0035 U4Random* rnd = U4Random::Get();
0036 if(rnd->isReady() == false)
0037 {
0038 LOG(LEVEL) << " index " << index << " NOT READY " ;
0039 return ;
0040 }
0041 rnd->setSequenceIndex(index);
0042 }
0043
0044 int U4Random::GetSequenceIndex()
0045 {
0046 if(U4Random::Get() == nullptr) return -1 ;
0047 U4Random* rnd = U4Random::Get();
0048 return rnd->isReady() ? rnd->getSequenceIndex() : -1 ;
0049 }
0050
0051
0052
0053
0054 const char* U4Random::SeqPath(){ return ssys::getenvvar(OPTICKS_RANDOM_SEQPATH, DEFAULT_SEQPATH ) ; }
0055
0056
0057 U4Random* U4Random::Create(const char* seq, const char* seqmask)
0058 {
0059 U4Random* rdm = new U4Random(seq, seqmask);
0060 bool ready = rdm->isReady();
0061 LOG_IF(fatal, !ready) << " NOT READY : \n" << rdm->detail() ;
0062 return ready ? rdm : nullptr ;
0063 }
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089 U4Random::U4Random(const char* seq, const char* seqmask)
0090 :
0091 m_seqpath_( seq ? seq : SeqPath() ),
0092 m_seqpath(spath::Resolve(m_seqpath_)),
0093 m_seqpath_exists( NP::Exists( m_seqpath ) || NP::ExistsArrayFolder(m_seqpath) ),
0094 m_seq(m_seqpath_exists ? NP::Load(m_seqpath) : nullptr),
0095 m_seq_values(m_seq ? m_seq->cvalues<float>() : nullptr ),
0096 m_seq_ni(m_seq ? m_seq->shape[0] : 0 ),
0097 m_seq_nv(m_seq ? m_seq->shape[1]*m_seq->shape[2] : 0 ),
0098 m_seq_index(-1),
0099
0100 m_cur(m_seq_ni > 0 ? NP::Make<int>(m_seq_ni) : nullptr),
0101 m_cur_values(m_cur ? m_cur->values<int>() : nullptr),
0102 m_recycle(true),
0103 m_default(CLHEP::HepRandom::getTheEngine()),
0104
0105 m_seqmask(seqmask ? NP::Load(seqmask) : nullptr),
0106 m_seqmask_ni( m_seqmask ? m_seqmask->shape[0] : 0 ),
0107 m_seqmask_values(m_seqmask ? m_seqmask->cvalues<size_t>() : nullptr),
0108
0109 m_flat_prior(0.),
0110 m_ready(false),
0111 m_select(ssys::getenvintvec("U4Random_select")),
0112 m_select_action(SDBG::Action(ssys::getenvvar("U4Random_select_action", "backtrace")))
0113 {
0114 init();
0115 }
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137
0138
0139
0140 bool U4Random::isSelect(int photon_idx, int flat_cursor) const
0141 {
0142 if(m_select == nullptr) return false ;
0143 assert( m_select->size() % 2 == 0 );
0144 for(unsigned p=0 ; p < m_select->size()/2 ; p++)
0145 {
0146 int _pidx = (*m_select)[p*2+0] ;
0147 int _cursor = (*m_select)[p*2+1] ;
0148 bool match = (( _pidx == photon_idx || _pidx == -1) && (_cursor == flat_cursor || _cursor == -1)) ;
0149 if(match) return true ;
0150 }
0151 return false ;
0152 }
0153
0154 std::string U4Random::descSelect(int photon_idx, int flat_cursor ) const
0155 {
0156 std::stringstream ss ;
0157 ss << "U4Random_select " << ssys::getenvvar("U4Random_select", "-")
0158 << " m_select->size " << ( m_select ? m_select->size() : 0 )
0159 ;
0160
0161 if(m_select)
0162 {
0163 for(unsigned p=0 ; p < m_select->size()/2 ; p++)
0164 {
0165 int _pidx = (*m_select)[p*2+0] ;
0166 int _cursor = (*m_select)[p*2+1] ;
0167 bool match = ( ( _pidx == photon_idx || _pidx == -1) && (_cursor == flat_cursor || _cursor == -1) ) ;
0168 ss << " (" << _pidx << "," << _cursor << ") " << ( match ? "YES" : "NO" ) << " " ;
0169 }
0170 }
0171 std::string s = ss.str();
0172 return s ;
0173 }
0174
0175
0176
0177 void U4Random::init()
0178 {
0179 INSTANCE = this ;
0180 m_ready = m_seq != nullptr ;
0181 LOG_IF(error, m_ready == false)
0182 << desc()
0183 << std::endl
0184 << NOTES
0185 << std::endl
0186 ;
0187
0188 LOG(LEVEL) << desc() ;
0189 }
0190
0191 bool U4Random::isReady() const { return m_ready ; }
0192
0193 std::string U4Random::desc() const
0194 {
0195 std::stringstream ss ;
0196 ss
0197 << "U4Random::desc"
0198 << " U4Random::isReady() " << ( m_ready ? "YES" : "NO" )
0199 << " m_seqpath " << ( m_seqpath ? m_seqpath : "-" )
0200 << " m_seq_ni " << m_seq_ni
0201 << " m_seq_nv " << m_seq_nv
0202 ;
0203 return ss.str();
0204 }
0205
0206 std::string U4Random::detail() const
0207 {
0208 std::stringstream ss ;
0209 ss << "U4Random::detail\n"
0210
0211 << std::setw(20) << "m_seqpath_" << " : " << ( m_seqpath_ ? m_seqpath_ : "-" ) << "\n"
0212 << std::setw(20) << "m_seqpath" << " : " << ( m_seqpath ? m_seqpath : "-" ) << "\n"
0213 << std::setw(20) << "m_seqpath_exists" << " : " << ( m_seqpath_exists ? "YES" : "NO " ) << "\n"
0214 << std::setw(20) << "m_seq" << " : " << ( m_seq ? m_seq->desc() : "-" ) << "\n"
0215 << std::setw(20) << "m_seq_index" << " : " << m_seq_index << "\n"
0216 << std::setw(20) << "m_cur" << " : " << ( m_cur ? m_cur->desc() : "-" ) << "\n"
0217 << std::setw(20) << "m_seqmask " << " : " << ( m_seqmask ? m_seqmask->desc() : "-" ) << "\n"
0218 << std::setw(20) << "desc \n" << desc() << "\n"
0219 ;
0220 std::string s = ss.str();
0221 return s ;
0222 }
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232
0233
0234 size_t U4Random::getNumIndices() const
0235 {
0236 return m_seq && m_seqmask ? m_seqmask_ni : ( m_seq ? m_seq_ni : 0 ) ;
0237 }
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250 void U4Random::SetSeed(long seed)
0251 {
0252 CLHEP::HepRandomEngine* engine = CLHEP::HepRandom::getTheEngine();
0253 int dummy = 0 ;
0254 engine->setSeed(seed, dummy);
0255 }
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269 size_t U4Random::getMaskedIndex(int index_)
0270 {
0271 if( m_seqmask == nullptr ) return index_ ;
0272 assert( index_ < m_seqmask_ni );
0273 size_t idx = m_seqmask_values[index_] ;
0274 return idx ;
0275 }
0276
0277
0278 int U4Random::getSequenceIndex() const
0279 {
0280 return m_seq_index ;
0281 }
0282
0283
0284
0285
0286
0287
0288
0289
0290
0291
0292
0293
0294
0295 void U4Random::setSequenceIndex(int index_)
0296 {
0297 LOG(LEVEL) << " index " << index_ ;
0298
0299 if( index_ < 0 )
0300 {
0301 #ifndef PRODUCTION
0302 #ifdef DEBUG_TAG
0303 check_cursor_vs_tagslot() ;
0304 #endif
0305 #endif
0306 m_seq_index = index_ ;
0307 disable() ;
0308 }
0309 else
0310 {
0311 size_t idx = getMaskedIndex(index_);
0312 bool idx_in_range = int(idx) < m_seq_ni ;
0313
0314 if(!idx_in_range)
0315 std::cout
0316 << "FATAL : OUT OF RANGE : "
0317 << " m_seq_ni " << m_seq_ni
0318 << " index_ " << index_
0319 << " idx " << idx << " (must be < m_seq_ni ) "
0320 << " desc " << desc()
0321 ;
0322 assert( idx_in_range );
0323 m_seq_index = idx ;
0324 enable();
0325 }
0326 }
0327
0328
0329 U4Random::~U4Random()
0330 {
0331 }
0332
0333
0334
0335
0336
0337
0338
0339
0340
0341
0342
0343 void U4Random::enable()
0344 {
0345 CLHEP::HepRandom::setTheEngine(this);
0346 }
0347
0348
0349
0350
0351
0352
0353
0354
0355
0356 void U4Random::disable()
0357 {
0358 CLHEP::HepRandom::setTheEngine(m_default);
0359 }
0360
0361
0362
0363
0364
0365
0366
0367
0368
0369
0370 void U4Random::dump(unsigned n)
0371 {
0372 for(unsigned i=0 ; i < n ; i++)
0373 {
0374 G4double u = G4UniformRand() ;
0375 std::cout
0376 << " i " << std::setw(5) << i
0377 << " u " << std::fixed << std::setw(10) << std::setprecision(5) << u
0378 << std::endl
0379 ;
0380 }
0381 }
0382
0383
0384
0385
0386
0387
0388
0389
0390
0391
0392
0393
0394 double U4Random::flat()
0395 {
0396 assert(m_seq_index > -1) ;
0397
0398 int cursor = *(m_cur_values + m_seq_index) ;
0399
0400 if( cursor >= m_seq_nv )
0401 {
0402 if(m_recycle == false)
0403 {
0404 std::cout
0405 << "U4Random::flat"
0406 << " FATAL : not enough precooked randoms and recycle not enabled "
0407 << " m_seq_index " << m_seq_index
0408 << " m_seq_nv " << m_seq_nv
0409 << " cursor " << cursor
0410 << std::endl
0411 ;
0412 assert(0);
0413 }
0414 else
0415 {
0416
0417
0418
0419
0420
0421
0422
0423
0424
0425
0426 cursor = cursor % m_seq_nv ;
0427 }
0428 }
0429
0430
0431
0432 int idx = m_seq_index*m_seq_nv + cursor ;
0433
0434 float f = m_seq_values[idx] ;
0435 double d = f ;
0436 m_flat_prior = d ;
0437
0438 *(m_cur_values + m_seq_index) += 1 ;
0439
0440 if(m_seq_index == SEvt::PIDX)
0441 {
0442 std::cout << "-------U4Random::flat" << std::endl << std::endl ;
0443 LOG(info)
0444 << " SEvt::PIDX " << SEvt::PIDX
0445 << " m_seq_index " << std::setw(4) << m_seq_index
0446 << " m_seq_nv " << std::setw(4) << m_seq_nv
0447 << " cursor " << std::setw(4) << cursor
0448 << " idx " << std::setw(4) << idx
0449 << " d " << std::setw(10 ) << std::fixed << std::setprecision(5) << d
0450 ;
0451
0452 char* summary = SBacktrace::Summary();
0453
0454 LOG(info) << std::endl << summary ;
0455
0456 }
0457
0458
0459 bool auto_tag = false ;
0460
0461 if( auto_tag )
0462 {
0463 char* summary = SBacktrace::Summary();
0464 unsigned stack = U4StackAuto::Classify(summary);
0465 bool is_classified = U4StackAuto::IsClassified(stack) ;
0466
0467
0468
0469 LOG_IF(error, !is_classified) << std::endl << summary ;
0470
0471 bool select = isSelect(m_seq_index, cursor ) || is_classified == false ;
0472 if( select )
0473 {
0474 LOG(info) << descSelect(m_seq_index, cursor) ;
0475 switch(m_select_action)
0476 {
0477 case SDBG::INTERRUPT: std::raise(SIGINT) ; break ;
0478 case SDBG::BACKTRACE: SBacktrace::Dump() ; break ;
0479 case SDBG::CALLER: SBacktrace::DumpCaller() ; break ;
0480 case SDBG::SUMMARY: SBacktrace::DumpSummary() ; break ;
0481 }
0482 }
0483
0484 #ifndef PRODUCTION
0485 SEvt::AddTag(1, stack, f );
0486 #endif
0487 }
0488
0489
0490 return d ;
0491 }
0492
0493
0494 #ifndef PRODUCTION
0495 #ifdef DEBUG_TAG
0496
0497
0498
0499
0500
0501
0502
0503
0504
0505
0506
0507
0508 void U4Random::check_cursor_vs_tagslot()
0509 {
0510 assert(m_seq_index > -1) ;
0511 int cursor = *(m_cur_values + m_seq_index) ;
0512
0513 if(SEvt::Exists(1) == false)
0514 {
0515 LOG(error) << " SEvt::Exists(1) false : cannot make this check " ;
0516 return ;
0517 }
0518
0519 int slot = SEvt::GetTagSlot(1);
0520 bool cursor_slot_match = cursor == slot ;
0521
0522
0523
0524 if(!cursor_slot_match)
0525 {
0526 m_problem_idx.push_back(m_seq_index);
0527 LOG(error)
0528 << " m_seq_index " << m_seq_index
0529 << " cursor " << cursor
0530 << " slot " << slot
0531 << " cursor_slot_match " << cursor_slot_match
0532 << std::endl
0533 << " PROBABLY SOME RANDOM CONSUMPTION LACKS SEvt::AddTag CALLS "
0534 ;
0535 }
0536 assert( cursor_slot_match );
0537 }
0538 #endif
0539 #endif
0540
0541
0542 void U4Random::saveProblemIdx(const char* fold) const
0543 {
0544 std::cout << "U4Random::saveProblemIdx m_problem_idx.size " << m_problem_idx.size() << " (" ;
0545 for(unsigned i=0 ; i < m_problem_idx.size() ; i++ ) std::cout << m_problem_idx[i] << " " ;
0546 std::cout << ")" << std::endl ;
0547
0548 NP::Write<int>( fold, "problem_idx.npy", m_problem_idx );
0549 }
0550
0551
0552
0553
0554
0555
0556
0557
0558
0559
0560
0561
0562
0563
0564
0565
0566
0567
0568
0569
0570
0571
0572
0573
0574
0575
0576
0577
0578
0579
0580
0581
0582
0583
0584 int U4Random::getFlatCursor() const
0585 {
0586 if(m_seq_index < 0) return -1 ;
0587 int cursor = *(m_cur_values + m_seq_index) ;
0588 return cursor ;
0589 }
0590
0591 double U4Random::getFlatPrior() const
0592 {
0593 return m_flat_prior ;
0594 }
0595
0596
0597
0598
0599
0600
0601
0602
0603
0604
0605 void U4Random::flatArray(const int size, double* vect)
0606 {
0607 assert(0);
0608 }
0609 void U4Random::setSeed(long seed, int)
0610 {
0611 assert(0);
0612 }
0613 void U4Random::setSeeds(const long * seeds, int)
0614 {
0615 assert(0);
0616 }
0617 void U4Random::saveStatus( const char filename[]) const
0618 {
0619 assert(0);
0620 }
0621 void U4Random::restoreStatus( const char filename[])
0622 {
0623 assert(0);
0624 }
0625 void U4Random::showStatus() const
0626 {
0627 assert(0);
0628 }
0629 std::string U4Random::name() const
0630 {
0631 return NAME ;
0632 }
0633