File indexing completed on 2026-04-09 07:49:08
0001 #include <sstream>
0002 #include <algorithm>
0003 #include <csignal>
0004
0005 #include "SLOG.hh"
0006 #include "spath.h"
0007 #include "scuda.h"
0008
0009 #include "NP.hh"
0010
0011 #include "QUDA_CHECK.h"
0012 #include "QRng.hh"
0013 #include "QCerenkovIntegral.hh"
0014
0015 #include "QCK.hh"
0016
0017
0018 const plog::Severity QCerenkovIntegral::LEVEL = SLOG::EnvLevel("QCerenkovIntegral", "DEBUG");
0019
0020
0021 const unsigned QCerenkovIntegral::SPLITBIN_PAYLOAD_SIZE = 8 ;
0022 const unsigned QCerenkovIntegral::UPPERCUT_PAYLOAD_SIZE = 3 ;
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038 QCerenkovIntegral::QCerenkovIntegral(const char* path_ )
0039 :
0040 path( spath::Resolve(path_) ),
0041 dsrc( NP::LoadIfExists(path)),
0042 src( nullptr ),
0043 emn(0.),
0044 emx(0.),
0045 rmn(0.),
0046 rmx(0.)
0047 {
0048 init();
0049 }
0050
0051
0052 void QCerenkovIntegral::init()
0053 {
0054 LOG_IF(error, dsrc == nullptr )
0055 << " FAILED to load "
0056 << " path " << path
0057 ;
0058 if(dsrc == nullptr) return ;
0059
0060 if(dsrc) src = dsrc->ebyte == 4 ? dsrc : NP::MakeNarrow(dsrc) ;
0061
0062 dsrc->pscale<double>(1e6, 0u) ;
0063 dsrc->minmax<double>(emn, emx, 0u );
0064 dsrc->minmax<double>(rmn, rmx, 1u );
0065
0066 LOG(info)
0067 << " emn " << std::setw(10) << std::fixed << std::setprecision(4) << emn
0068 << " emx " << std::setw(10) << std::fixed << std::setprecision(4) << emx
0069 << " rmn " << std::setw(10) << std::fixed << std::setprecision(4) << rmn
0070 << " rmx " << std::setw(10) << std::fixed << std::setprecision(4) << rmx
0071 ;
0072
0073
0074
0075 }
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095
0096
0097 template <typename T>
0098 NP* QCerenkovIntegral::GetAverageNumberOfPhotons_s2_(T& emin, T& emax, const T BetaInverse, const T charge ) const
0099 {
0100 emin = emx ;
0101 emax = emn ;
0102
0103 const T* vv = dsrc->cvalues<T>();
0104 unsigned ni = dsrc->shape[0] ;
0105 unsigned nj = dsrc->shape[1] ;
0106
0107 bool dsrc_expect = nj == 2 && ni > 1 ;
0108 assert(dsrc_expect);
0109 if(!dsrc_expect) std::raise(SIGINT);
0110
0111 T s2integral(0.) ;
0112
0113 T en_a = -1. ;
0114 T ri_a = -1. ;
0115 T en_b = -1. ;
0116 T ri_b = -1. ;
0117
0118 NP* s2i = NP::Make<T>(ni) ;
0119 T* s2i_vv = s2i->values<T>();
0120 bool dump = false ;
0121
0122 for(unsigned i=0 ; i < ni - 1 ; i++)
0123 {
0124 T en_0 = vv[2*(i+0)+0] ;
0125 T en_1 = vv[2*(i+1)+0] ;
0126
0127 T ri_0 = vv[2*(i+0)+1] ;
0128 T ri_1 = vv[2*(i+1)+1] ;
0129
0130 T bin_integral = charge*charge*GetS2Integral_WithCut<T>( emin, emax, BetaInverse, en_0, en_1, ri_0, ri_1, en_a, ri_a, en_b, ri_b, dump );
0131
0132 s2i_vv[i] = bin_integral ;
0133 s2integral += bin_integral ;
0134 }
0135 return s2i ;
0136 }
0137 template NP* QCerenkovIntegral::GetAverageNumberOfPhotons_s2_<double>(double& emin, double& emax, const double BetaInverse, const double charge ) const ;
0138 template NP* QCerenkovIntegral::GetAverageNumberOfPhotons_s2_<float>( float& emin, float& emax, const float BetaInverse, const float charge ) const ;
0139
0140
0141
0142 template <typename T>
0143 T QCerenkovIntegral::GetAverageNumberOfPhotons_s2(T& emin, T& emax, const T BetaInverse, const T charge ) const
0144 {
0145 NP* s2i = GetAverageNumberOfPhotons_s2_<T>(emin, emax, BetaInverse, charge );
0146 T s2integral = s2i->psum<T>(0u);
0147 return s2integral ;
0148 }
0149
0150 template double QCerenkovIntegral::GetAverageNumberOfPhotons_s2<double>(double& emin, double& emax, const double BetaInverse, const double charge ) const ;
0151 template float QCerenkovIntegral::GetAverageNumberOfPhotons_s2<float>( float& emin, float& emax, const float BetaInverse, const float charge ) const ;
0152
0153
0154
0155 template <typename T>
0156 NP* QCerenkovIntegral::getAverageNumberOfPhotons_s2( const NP* bis ) const
0157 {
0158 T emin ;
0159 T emax ;
0160 T charge = T(1.) ;
0161
0162 unsigned ni = bis->shape[0] ;
0163 NP* avph = NP::Make<T>(ni, 4 );
0164 T* avph_v = avph->values<T>();
0165
0166 for(unsigned i=0 ; i < ni ; i++)
0167 {
0168 const T BetaInverse = bis->get<T>(i) ;
0169 T avgNumPhotons = GetAverageNumberOfPhotons_s2<T>(emin, emax, BetaInverse, charge );
0170
0171 avph_v[4*i+0] = BetaInverse ;
0172 avph_v[4*i+1] = emin ;
0173 avph_v[4*i+2] = emax ;
0174 avph_v[4*i+3] = avgNumPhotons ;
0175 }
0176 return avph ;
0177 }
0178
0179 template NP* QCerenkovIntegral::getAverageNumberOfPhotons_s2<float>( const NP* ) const ;
0180 template NP* QCerenkovIntegral::getAverageNumberOfPhotons_s2<double>( const NP* ) const ;
0181
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191 const double QCerenkovIntegral::FINE_STRUCTURE_OVER_HBARC_EVMM = 36.981 ;
0192
0193 const char* QCerenkovIntegral::NONE_ = "NONE" ;
0194 const char* QCerenkovIntegral::UNCUT_ = "UNCUT" ;
0195 const char* QCerenkovIntegral::SUB_ = "SUB" ;
0196 const char* QCerenkovIntegral::CUT_ = "CUT" ;
0197 const char* QCerenkovIntegral::FULL_ = "FULL" ;
0198 const char* QCerenkovIntegral::PART_ = "PART" ;
0199 const char* QCerenkovIntegral::ERR_ = "ERR" ;
0200
0201 const char* QCerenkovIntegral::State(int state)
0202 {
0203 const char* s = nullptr ;
0204 switch(state)
0205 {
0206 case NONE: s = NONE_ ; break ;
0207 case SUB: s = SUB_ ; break ;
0208 case UNCUT: s = UNCUT_ ; break ;
0209 case CUT: s = CUT_ ; break ;
0210 case FULL: s = FULL_ ; break ;
0211 case PART: s = PART_ ; break ;
0212 case ERR: s = ERR_ ; break ;
0213 }
0214 return s ;
0215 }
0216
0217
0218
0219
0220
0221
0222
0223
0224
0225
0226
0227
0228
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260
0261
0262
0263
0264
0265
0266
0267
0268
0269
0270
0271
0272
0273
0274
0275
0276
0277
0278
0279
0280
0281
0282
0283
0284
0285
0286
0287 template<typename T>
0288 T QCerenkovIntegral::GetS2Integral_WithCut( T& emin, T& emax, T BetaInverse, T en_0, T en_1 , T ri_0, T ri_1, T en_a, T ri_a, T en_b, T ri_b, bool dump )
0289 {
0290
0291 int state = NONE ;
0292 if( en_b <= 0. ) state = UNCUT ;
0293 else if( en_a >= en_0 && en_b <= en_1 ) state = SUB ;
0294 else if( en_0 > en_b && en_1 > en_b ) state = CUT ;
0295 else if( en_0 < en_b && en_1 <= en_b ) state = FULL ;
0296 else if( en_0 <= en_b && en_b < en_1 ) state = PART ;
0297 else state = ERR ;
0298
0299 bool missed_condition = state == ERR || state == NONE ;
0300
0301 LOG_IF(error, missed_condition) << " missed condition ?" << " en_0 " << en_0 << " en_1 " << en_1 << " en_a " << en_a << " en_b " << en_b ;
0302
0303 const T zero(0.) ;
0304 if( state == CUT ) return zero ;
0305 assert( state == FULL || state == PART || state == UNCUT || state == SUB );
0306 if(state == SUB) assert( en_a >= en_0 && en_b <= en_1 );
0307
0308 const T one(1.) ;
0309 const T half(0.5) ;
0310 T s2integral(0.) ;
0311
0312 T ct_0 = BetaInverse/ri_0 ;
0313 T ct_1 = BetaInverse/ri_1 ;
0314 T ct_a = en_a > 0 ? BetaInverse/ri_a : -1 ;
0315 T ct_b = en_b > 0 ? BetaInverse/ri_b : -1 ;
0316 T s2_0 = ( one - ct_0 )*( one + ct_0 );
0317 T s2_1 = ( one - ct_1 )*( one + ct_1 );
0318 T s2_a = en_a > 0 ? ( one - ct_a )*( one + ct_a ) : -1 ;
0319 T s2_b = en_b > 0 ? ( one - ct_b )*( one + ct_b ) : -1 ;
0320
0321 if(dump) std::cout
0322 << "QCerenkovIntegral::GetS2Integral_WithCut"
0323 << " en_0 " << en_0
0324 << " en_1 " << en_1
0325 << " en_a " << en_a
0326 << " en_b " << en_b
0327 << " s2_0 " << s2_0
0328 << " s2_1 " << s2_1
0329 << " s2_a " << s2_a
0330 << " s2_b " << s2_b
0331 << " state " << State(state)
0332 << " BetaInverse " << BetaInverse
0333 << std::endl
0334 ;
0335
0336
0337 bool cross = s2_0*s2_1 < zero ;
0338 T en_cross = cross ? en_0 + (BetaInverse - ri_0)*(en_1 - en_0)/(ri_1 - ri_0) : -one ;
0339
0340
0341 if( s2_0 < zero && s2_1 > zero )
0342 {
0343 assert( en_cross > zero );
0344
0345 if( state == FULL || state == UNCUT )
0346 {
0347 s2integral = (en_1 - en_cross)*s2_1*half ;
0348
0349 emin = std::min<T>( emin, en_cross );
0350 emax = std::max<T>( emax, en_1 );
0351 }
0352 else if (state == PART )
0353 {
0354 s2integral = en_b <= en_cross ? zero : (en_b - en_cross)*s2_b*half ;
0355
0356 emin = std::min<T>( emin, en_b <= en_cross ? emin : en_cross );
0357 emax = std::max<T>( emax, emax );
0358 }
0359 else if (state == SUB )
0360 {
0361
0362
0363
0364
0365
0366
0367
0368
0369
0370
0371
0372
0373
0374
0375
0376
0377
0378
0379
0380 if( en_a <= en_cross && en_b <= en_cross )
0381 {
0382 s2integral = zero ;
0383 }
0384 else
0385 {
0386 if( en_a <= en_cross && en_b >= en_cross )
0387 {
0388 s2integral = (en_b - en_cross)*s2_b*half ;
0389 emin = std::min<T>( emin, en_cross ) ;
0390 emax = std::min<T>( emax, en_b ) ;
0391 }
0392 else
0393 {
0394 s2integral = (en_b - en_a)*(s2_a + s2_b)*half ;
0395 emin = std::min<T>( emin, en_a ) ;
0396 emax = std::min<T>( emax, en_b ) ;
0397 }
0398 }
0399 }
0400 }
0401 else if( s2_0 >= zero && s2_1 >= zero )
0402 {
0403 if( state == FULL || state == UNCUT )
0404 {
0405 s2integral = (en_1 - en_0)*(s2_0 + s2_1)*half ;
0406
0407 emin = std::min<T>( emin, en_0 );
0408 emax = std::max<T>( emax, en_1 );
0409 }
0410 else if( state == PART )
0411 {
0412 s2integral = (en_b - en_0)*(s2_0 + s2_b)*half ;
0413 if(dump) std::cout << " s2 +ve across full bin " << " s2integral " << s2integral << std::endl ;
0414 emin = std::min<T>( emin, en_0 );
0415 emax = std::max<T>( emax, en_b );
0416 }
0417 else if (state == SUB )
0418 {
0419 s2integral = (en_b - en_a)*(s2_a + s2_b)*half ;
0420 emin = std::min<T>( emin, en_a );
0421 emax = std::max<T>( emax, en_b );
0422 }
0423 }
0424 else if( s2_0 > zero && s2_1 < zero )
0425 {
0426 assert( en_cross > zero );
0427
0428 if( state == FULL || state == UNCUT )
0429 {
0430 s2integral = (en_cross - en_0)*s2_0*half ;
0431
0432 emin = std::min<T>( emin, en_0 );
0433 emax = std::max<T>( emax, en_cross );
0434
0435 }
0436 else if( state == PART )
0437 {
0438 s2integral = en_b >= en_cross ? (en_cross - en_0)*s2_0*half : (en_b - en_0)*(s2_0+s2_b)*half ;
0439
0440 emin = std::min<T>( emin, en_0 );
0441 emax = std::max<T>( emax, en_b >= en_cross ? en_cross : en_b );
0442 }
0443 else if (state == SUB )
0444 {
0445
0446
0447
0448
0449
0450
0451
0452
0453
0454
0455
0456
0457
0458
0459
0460
0461
0462
0463
0464
0465
0466
0467 if( en_a <= en_cross && en_b <= en_cross )
0468 {
0469 s2integral = (en_b - en_a)*(s2_a + s2_b)*half ;
0470 emin = std::min<T>( emin, en_a ) ;
0471 emax = std::min<T>( emax, en_b ) ;
0472 }
0473 else
0474 {
0475 if( en_a <= en_cross && en_b >= en_cross )
0476 {
0477 s2integral = (en_cross - en_a)*s2_a*half ;
0478 emin = std::min<T>( emin, en_a ) ;
0479 emax = std::min<T>( emax, en_cross ) ;
0480 }
0481 else
0482 {
0483 s2integral = zero ;
0484 }
0485 }
0486 }
0487 }
0488 const T Rfact = FINE_STRUCTURE_OVER_HBARC_EVMM ;
0489 return Rfact*s2integral ;
0490 }
0491
0492 template float QCerenkovIntegral::GetS2Integral_WithCut( float& , float&, float, float, float, float, float, float, float, float, float, bool );
0493 template double QCerenkovIntegral::GetS2Integral_WithCut( double&, double&, double, double, double, double, double, double, double, double, double, bool );
0494
0495
0496
0497
0498
0499
0500
0501
0502
0503
0504 template <typename T> NP* QCerenkovIntegral::getS2Integral_WithCut_( T& emin, T& emax, T BetaInverse, T en_a, T en_b, bool dump ) const
0505 {
0506 const T* vv = dsrc->cvalues<T>();
0507 unsigned ni = dsrc->shape[0] ;
0508 unsigned nj = dsrc->shape[1] ;
0509 bool dsrc_expect = nj == 2 && ni > 1 ;
0510 assert(dsrc_expect );
0511 if(!dsrc_expect) std::raise(SIGINT);
0512
0513 NP* s2i = NP::Make<T>(ni);
0514 T* s2i_vv = s2i->values<T>();
0515
0516 T ri_a = en_a > 0 ? dsrc->interp<T>(en_a) : -1 ;
0517 T ri_b = en_b > 0 ? dsrc->interp<T>(en_b) : -1 ;
0518
0519 for(unsigned i=0 ; i < ni - 1 ; i++)
0520 {
0521 T en_0 = vv[2*(i+0)+0] ;
0522 T en_1 = vv[2*(i+1)+0] ;
0523
0524 T ri_0 = vv[2*(i+0)+1] ;
0525 T ri_1 = vv[2*(i+1)+1] ;
0526
0527 s2i_vv[i] = GetS2Integral_WithCut<T>(emin, emax, BetaInverse, en_0, en_1, ri_0, ri_1, en_a, ri_a, en_b, ri_b, dump );
0528 }
0529 return s2i ;
0530 }
0531
0532 template NP* QCerenkovIntegral::getS2Integral_WithCut_( double&, double&, double, double, double, bool ) const ;
0533 template NP* QCerenkovIntegral::getS2Integral_WithCut_( float&, float&, float, float, float, bool ) const ;
0534
0535
0536
0537 template <typename T>
0538 T QCerenkovIntegral::getS2Integral_WithCut( T& emin, T& emax, T BetaInverse, T en_a, T en_b, bool dump ) const
0539 {
0540 NP* s2i = getS2Integral_WithCut_<T>(emin, emax, BetaInverse, en_a, en_b, dump );
0541 T s2integral = s2i->psum<T>(0u);
0542 return s2integral ;
0543 }
0544 template double QCerenkovIntegral::getS2Integral_WithCut( double&, double&, double, double, double, bool ) const ;
0545 template float QCerenkovIntegral::getS2Integral_WithCut( float&, float&, float, float, float, bool ) const ;
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
0572
0573
0574
0575
0576
0577
0578
0579
0580
0581
0582
0583
0584
0585
0586
0587
0588
0589
0590
0591
0592
0593
0594
0595
0596
0597
0598
0599
0600
0601
0602
0603
0604
0605
0606
0607
0608
0609
0610
0611
0612
0613
0614
0615
0616
0617
0618
0619
0620
0621
0622
0623
0624
0625
0626
0627
0628
0629
0630
0631
0632
0633
0634
0635
0636
0637
0638 template <typename T>
0639 NP* QCerenkovIntegral::getS2Integral_SplitBin(const T BetaInverse, unsigned mul, bool dump ) const
0640 {
0641 T emin, emax ;
0642 T charge = T(1.) ;
0643 T avgNumPhotons = GetAverageNumberOfPhotons_s2<T>(emin, emax, BetaInverse, charge );
0644 if(avgNumPhotons <= 0. ) return nullptr ;
0645
0646 LOG(debug)
0647 << " emin " << std::setw(10) << std::fixed << std::setprecision(4) << emin
0648 << " emax " << std::setw(10) << std::fixed << std::setprecision(4) << emax
0649 ;
0650
0651 const T* ri_v = dsrc->cvalues<T>();
0652
0653 unsigned ri_ni = dsrc->shape[0] ;
0654 unsigned ri_nj = dsrc->shape[1] ;
0655
0656 bool dsrc_expect = ri_nj == 2 && ri_ni > 1 ;
0657 assert(dsrc_expect );
0658 if(!dsrc_expect) std::raise(SIGINT);
0659
0660 unsigned ns = 1+mul ;
0661 unsigned s2_edges = getNumEdges_SplitBin<T>(mul);
0662
0663 NP* s2c = NP::Make<T>(s2_edges, SPLITBIN_PAYLOAD_SIZE) ;
0664 T* s2c_v = s2c->values<T>();
0665
0666 std::vector<unsigned> idxs ;
0667 unsigned idx = 0 ;
0668 for(unsigned p=0 ; p < SPLITBIN_PAYLOAD_SIZE ; p++) s2c_v[SPLITBIN_PAYLOAD_SIZE*idx + p] = ( p == 0 || p == 1) ? emn : 0. ;
0669
0670 idxs.push_back(idx);
0671
0672 T s2integral = 0. ;
0673
0674 for(unsigned i=0 ; i < ri_ni - 1 ; i++)
0675 {
0676 T en_0 = ri_v[2*(i+0)+0] ;
0677 T ri_0 = ri_v[2*(i+0)+1] ;
0678
0679 T en_1 = ri_v[2*(i+1)+0] ;
0680 T ri_1 = ri_v[2*(i+1)+1] ;
0681
0682 T en_01 = en_1 - en_0 ;
0683
0684 if(dump) std::cout
0685 << "QCerenkovIntegral::getS2Integral_splitbin"
0686 << " i " << std::setw(3) << i
0687 << " ns " << std::setw(3) << ns
0688 << " en_0 " << std::setw(10) << std::fixed << std::setprecision(4) << en_0
0689 << " en_1 " << std::setw(10) << std::fixed << std::setprecision(4) << en_1
0690 << std::endl
0691 ;
0692
0693
0694 for(unsigned s=1 ; s < 1+mul ; s++)
0695 {
0696 T en_a = en_0 + en_01*T(s-1)/T(mul) ;
0697 T en_b = en_0 + en_01*T(s+0)/T(mul) ;
0698
0699 T ri_a = en_a > 0. ? dsrc->interp<T>(en_a) : -1 ;
0700 T ri_b = en_b > 0. ? dsrc->interp<T>(en_b) : -1 ;
0701
0702 T s2_a = getS2<T>( BetaInverse, en_a );
0703 T s2_b = getS2<T>( BetaInverse, en_b );
0704
0705 T sub = GetS2Integral_WithCut<T>(emin, emax, BetaInverse, en_0, en_1, ri_0, ri_1, en_a, ri_a, en_b, ri_b, dump );
0706
0707 s2integral += sub ;
0708
0709 unsigned idx = i*mul + s ;
0710 idxs.push_back(idx);
0711 assert( idx < s2_edges );
0712
0713 s2c_v[SPLITBIN_PAYLOAD_SIZE*idx + 0 ] = en_b ;
0714 s2c_v[SPLITBIN_PAYLOAD_SIZE*idx + 1 ] = en_a ;
0715 s2c_v[SPLITBIN_PAYLOAD_SIZE*idx + 2 ] = ri_a ;
0716 s2c_v[SPLITBIN_PAYLOAD_SIZE*idx + 3 ] = ri_b ;
0717 s2c_v[SPLITBIN_PAYLOAD_SIZE*idx + 4 ] = s2_a ;
0718 s2c_v[SPLITBIN_PAYLOAD_SIZE*idx + 5 ] = s2_b ;
0719 s2c_v[SPLITBIN_PAYLOAD_SIZE*idx + 6 ] = sub ;
0720 s2c_v[SPLITBIN_PAYLOAD_SIZE*idx + 7 ] = s2integral ;
0721 }
0722 }
0723
0724 for(unsigned i=0 ; i < idxs.size() ; i++) assert( idxs[i] == i );
0725 return s2c ;
0726 }
0727
0728
0729 template NP* QCerenkovIntegral::getS2Integral_SplitBin( const double, unsigned, bool ) const ;
0730 template NP* QCerenkovIntegral::getS2Integral_SplitBin( const float, unsigned, bool ) const ;
0731
0732
0733 template<typename T>
0734 unsigned QCerenkovIntegral::getNumEdges_SplitBin(unsigned mul ) const
0735 {
0736 unsigned ri_ni = dsrc->shape[0] ;
0737 unsigned ri_bins = ri_ni - 1 ;
0738 unsigned s2_bins = ri_bins*mul ;
0739 return s2_bins + 1 ;
0740 }
0741
0742
0743
0744
0745
0746 template unsigned QCerenkovIntegral::getNumEdges_SplitBin<float>(unsigned ) const ;
0747 template unsigned QCerenkovIntegral::getNumEdges_SplitBin<double>(unsigned ) const ;
0748
0749
0750
0751
0752
0753
0754
0755
0756
0757
0758 template <typename T>
0759 NP* QCerenkovIntegral::getS2Integral_SplitBin( const NP* bis, unsigned mul, bool dump) const
0760 {
0761 unsigned ni = bis->shape[0] ;
0762 unsigned s2_edges = getNumEdges_SplitBin<T>(mul);
0763 unsigned nj = s2_edges ;
0764
0765 NP* s2c = NP::Make<T>(ni, nj, SPLITBIN_PAYLOAD_SIZE) ;
0766
0767 LOG(LEVEL) << "[ creating s2c " << s2c->sstr() ;
0768
0769 for(unsigned i=0 ; i < ni ; i++)
0770 {
0771 const T BetaInverse = bis->get<T>(i) ;
0772 NP* s2c_one = getS2Integral_SplitBin<T>(BetaInverse, mul, dump );
0773
0774 if(s2c_one == nullptr)
0775 {
0776 LOG(info)
0777 << " s2c_one NULL "
0778 << " i " << i
0779 << " ni " << ni
0780 << " BetaInverse " << std::setw(10) << std::fixed << std::setprecision(4) << BetaInverse
0781 ;
0782 continue;
0783 }
0784 unsigned s2c_one_bytes = s2c_one->arr_bytes() ;
0785 memcpy( s2c->bytes() + i*s2c_one_bytes, s2c_one->bytes(), s2c_one_bytes );
0786 s2c_one->clear();
0787 }
0788 LOG(LEVEL) << "] creating s2c " << s2c->sstr() ;
0789 return s2c ;
0790 }
0791
0792 template NP* QCerenkovIntegral::getS2Integral_SplitBin<float>( const NP*, unsigned, bool) const ;
0793 template NP* QCerenkovIntegral::getS2Integral_SplitBin<double>( const NP*, unsigned, bool) const ;
0794
0795
0796
0797
0798 template <typename T>
0799 T QCerenkovIntegral::getS2( const T BetaInverse, const T en ) const
0800 {
0801 const T one(1.) ;
0802 T ri = dsrc->interp<T>(en) ;
0803 T ct = BetaInverse/ri ;
0804 T s2 = ( one - ct )*( one + ct );
0805 return s2 ;
0806 }
0807
0808 template double QCerenkovIntegral::getS2( const double, const double ) const ;
0809 template float QCerenkovIntegral::getS2( const float, const float ) const ;
0810
0811
0812
0813
0814
0815
0816
0817
0818
0819
0820
0821
0822
0823
0824
0825
0826
0827
0828
0829
0830
0831
0832 template <typename T>
0833 NP* QCerenkovIntegral::getS2Integral_UpperCut( const T BetaInverse, unsigned nx ) const
0834 {
0835 T emin ;
0836 T emax ;
0837 T charge = T(1.) ;
0838
0839 T avgNumPhotons = GetAverageNumberOfPhotons_s2<T>(emin, emax, BetaInverse, charge );
0840 if(avgNumPhotons <= 0. ) return nullptr ;
0841
0842
0843 NP* s2c = NP::Make<T>(nx, UPPERCUT_PAYLOAD_SIZE) ;
0844 T* cc = s2c->values<T>();
0845
0846 NP* full_s2i = GetAverageNumberOfPhotons_s2_<T>(emin, emax, BetaInverse, charge );
0847
0848 LOG(debug)
0849 << " BetaInverse " << std::setw(10) << std::fixed << std::setprecision(4) << BetaInverse
0850 << " emin " << std::setw(10) << std::fixed << std::setprecision(4) << emin
0851 << " emax " << std::setw(10) << std::fixed << std::setprecision(4) << emax
0852 << " avgNumPhotons " << std::setw(10) << std::fixed << std::setprecision(4) << avgNumPhotons
0853 << " avgNumPhotons*1e6 " << std::setw(10) << std::fixed << std::setprecision(4) << avgNumPhotons*1e6
0854 ;
0855
0856 const NP* edom = NP::Linspace<T>( emin, emax, nx );
0857 const T* ee = edom->cvalues<T>();
0858
0859 T last_ecut = 0. ;
0860 T last_s2integral = 0. ;
0861 NP* last_s2i = nullptr ;
0862 bool dump = false ;
0863
0864
0865
0866
0867
0868
0869 for(unsigned i=0 ; i < nx ; i++)
0870 {
0871 T en_a = -1. ;
0872 T en_b = ee[i] ;
0873
0874 NP* s2i = getS2Integral_WithCut_<T>(emin, emax, BetaInverse, en_a, en_b, dump );
0875
0876 T s2integral = s2i->psum<T>(0u);
0877 T s2_b = getS2<T>( BetaInverse, en_b );
0878
0879 cc[UPPERCUT_PAYLOAD_SIZE*i+0] = en_b ;
0880 cc[UPPERCUT_PAYLOAD_SIZE*i+1] = s2_b ;
0881 cc[UPPERCUT_PAYLOAD_SIZE*i+2] = s2integral ;
0882
0883 if( i == nx - 1 )
0884 {
0885 last_ecut = en_b ;
0886 last_s2integral = s2integral ;
0887 last_s2i = s2i ;
0888 }
0889 else
0890 {
0891 s2i->clear();
0892 }
0893 }
0894
0895 T diff = std::abs(avgNumPhotons - last_s2integral);
0896 bool close = diff < 1e-6 ;
0897 if(!close)
0898 {
0899 std::cout << "NP::DumpCompare a:full_s2i b:last_s2i " << std::endl;
0900 NP::DumpCompare<double>( full_s2i, last_s2i, 0u, 0u, 1e-6 );
0901
0902 std::cout
0903 << " QCerenkovIntegral::getS2Integral_UpperCut "
0904 << " BetaInverse " << std::setw(10) << std::fixed << std::setprecision(4) << BetaInverse
0905 << " avgNumPhotons " << std::setw(10) << std::fixed << std::setprecision(4) << avgNumPhotons
0906 << " last_ecut " << std::setw(10) << std::fixed << std::setprecision(4) << last_ecut
0907 << " last_s2integral " << std::setw(10) << std::fixed << std::setprecision(4) << last_s2integral
0908 << " diff " << std::setw(10) << std::fixed << std::setprecision(4) << diff
0909 << " close " << close
0910 << std::endl
0911 ;
0912 }
0913 assert(close);
0914
0915 return s2c ;
0916 }
0917
0918 template NP* QCerenkovIntegral::getS2Integral_UpperCut( const double BetaInverse, unsigned nx ) const ;
0919 template NP* QCerenkovIntegral::getS2Integral_UpperCut( const float BetaInverse, unsigned nx ) const ;
0920
0921
0922
0923
0924
0925
0926
0927
0928
0929
0930
0931 template <typename T>
0932 NP* QCerenkovIntegral::getS2Integral_UpperCut( const NP* bis, unsigned nx ) const
0933 {
0934 unsigned ni = bis->shape[0] ;
0935 const T* bb = bis->cvalues<T>();
0936 unsigned nj = nx ;
0937
0938 NP* s2c = NP::Make<T>(ni, nj, 3) ;
0939 LOG(info) << "[ creating s2c " << s2c->sstr() ;
0940
0941 for(unsigned i=0 ; i < ni ; i++)
0942 {
0943 const T BetaInverse = bb[i] ;
0944 NP* s2c_one = getS2Integral_UpperCut<T>(BetaInverse, nx );
0945
0946 if(s2c_one == nullptr)
0947 {
0948 LOG(info)
0949 << " s2c_one NULL "
0950 << " i " << i
0951 << " ni " << ni
0952 << " BetaInverse " << std::setw(10) << std::fixed << std::setprecision(4) << BetaInverse
0953 ;
0954 continue;
0955 }
0956 unsigned s2c_one_bytes = s2c_one->arr_bytes() ;
0957 memcpy( s2c->bytes() + i*s2c_one_bytes, s2c_one->bytes(), s2c_one_bytes );
0958 s2c_one->clear();
0959 }
0960 LOG(info) << "] creating s2c " << s2c->sstr() ;
0961 return s2c ;
0962 }
0963
0964 template NP* QCerenkovIntegral::getS2Integral_UpperCut<double>( const NP* , unsigned ) const ;
0965 template NP* QCerenkovIntegral::getS2Integral_UpperCut<float>( const NP* , unsigned ) const ;
0966
0967
0968
0969
0970
0971
0972
0973
0974
0975
0976
0977
0978
0979 template <typename T>
0980 QCK<T> QCerenkovIntegral::makeICDF_UpperCut( unsigned ny, unsigned nx, bool dump) const
0981 {
0982 NP* bis = NP::Linspace<T>( 1. , rmx, ny ) ;
0983 NP* avph = getAverageNumberOfPhotons_s2<T>(bis );
0984 NP* s2c = getS2Integral_UpperCut<T>( bis, nx );
0985 NP* s2cn = s2c->copy();
0986 s2cn->divide_by_last<T>();
0987
0988 unsigned nu = 1000 ;
0989 unsigned hd_factor = 10 ;
0990
0991 NP* icdf = NP::MakeICDF<T>(s2cn, nu, hd_factor, dump);
0992 icdf->set_meta<std::string>("creator", "QCerenkovIntegral::makeICDF_UpperCut") ;
0993 icdf->set_meta<unsigned>("hd_factor", hd_factor );
0994
0995 NP* icdf_prop = NP::MakeProperty<T>( icdf, hd_factor ) ;
0996 icdf_prop->set_meta<std::string>("creator", "QCerenkovIntegral::makeICDF_UpperCut") ;
0997 icdf_prop->set_meta<unsigned>("hd_factor", hd_factor );
0998
0999
1000 QCK<T> qck ;
1001
1002 qck.rindex = dsrc ;
1003 qck.bis = bis ;
1004 qck.avph = avph ;
1005 qck.s2c = s2c ;
1006 qck.s2cn = s2cn ;
1007 qck.icdf = icdf ;
1008 qck.icdf_prop = icdf_prop ;
1009
1010 return qck ;
1011 }
1012 template QCK<double> QCerenkovIntegral::makeICDF_UpperCut<double>( unsigned , unsigned, bool ) const ;
1013 template QCK<float> QCerenkovIntegral::makeICDF_UpperCut<float>( unsigned , unsigned, bool ) const ;
1014
1015
1016
1017
1018 template <typename T>
1019 QCK<T> QCerenkovIntegral::makeICDF_SplitBin( unsigned ny, unsigned mul, bool dump) const
1020 {
1021 NP* bis = NP::Linspace<T>( 1. , rmx, ny ) ;
1022 std::stringstream ss ;
1023 ss << "name:makeICDF_SplitBin,mul:" << mul ;
1024 bis->meta = ss.str();
1025
1026 NP* avph = getAverageNumberOfPhotons_s2<T>(bis );
1027 NP* s2c = getS2Integral_SplitBin<T>( bis, mul, dump );
1028 NP* s2cn = s2c->copy();
1029 s2cn->divide_by_last<T>();
1030
1031 unsigned nu = 1000 ;
1032 unsigned hd_factor = 10 ;
1033 NP* icdf = NP::MakeICDF<T>(s2cn, nu, hd_factor, dump);
1034 icdf->set_meta<std::string>("creator", "QCerenkovIntegral::makeICDF_SplitBin") ;
1035 icdf->set_meta<unsigned>("hd_factor", hd_factor );
1036
1037 NP* icdf_prop = NP::MakeProperty<T>( icdf, hd_factor ) ;
1038 icdf_prop->set_meta<std::string>("creator", "QCerenkovIntegral::makeICDF_UpperCut") ;
1039 icdf_prop->set_meta<unsigned>("hd_factor", hd_factor );
1040
1041
1042 QCK<T> qck ;
1043
1044 qck.rindex = dsrc ;
1045 qck.bis = bis ;
1046 qck.avph = avph ;
1047 qck.s2c = s2c ;
1048 qck.s2cn = s2cn ;
1049 qck.icdf = icdf ;
1050 qck.icdf_prop = icdf_prop ;
1051
1052 return qck ;
1053 }
1054 template QCK<double> QCerenkovIntegral::makeICDF_SplitBin<double>( unsigned , unsigned, bool ) const ;
1055 template QCK<float> QCerenkovIntegral::makeICDF_SplitBin<float>( unsigned , unsigned, bool ) const ;
1056
1057