43                                  {
   44  cout << 
"JMarkovPathGenerator version " << 
MPG_VERSION << endl 
 
   45       << "Written by Martijn Jongen" << endl 
   46       << endl ; 
   47  cout << "Type '" << argv[0] << " -h!' to display the command-line options." << endl ;
   48  cout << endl ;
   49 
   50  string outfile = "out.paths"  ; 
   51  string smoutfile = ""        ; 
   52  double lHG = 60.241          ; 
   53  double g   = 0.924           ; 
   54  double lR  = 294.118         ; 
   56  double lA  = 50              ; 
   57  double d = 37                ; 
   58  int npaths = 100             ; 
   59  int nscat = 2                ; 
   60  int interval = 1000          ; 
   61  int burnIn = 50000           ; 
   62  double stepsize = 10         ; 
   63  bool sourceNB                ;
   64  double target_zenith         ;
   65 
   66  try {
   68    zap[
"o"] = 
make_field(outfile,
"output file name") ;
 
   69    zap[
"O"] = 
make_field(smoutfile,
"OPTIONAL: output file name for scattering model") ;
 
   70    zap[
"-lH"] = 
make_field(lHG,
"scattering length in m for Henyey-Greenstein scattering") ;
 
   71    zap[
"g"] = 
make_field(g,
"parameter g for Henyey-Greenstein function") ;
 
   72    zap[
"R"] = 
make_field(lR,
"scattering length in m for Rayleigh scattering") ;
 
   73    zap[
"a"] = 
make_field(a,
"parameter a for Rayleigh scattering") ;
 
   74    zap[
"A"] = 
make_field(lA,
"absorption length in m") ;
 
   75    zap[
"d"] = 
make_field(d,
"distance between source and target in m") ;
 
   76    zap[
"n"] = 
make_field(npaths,
"number of paths to generate") ;
 
   77    zap[
"N"] = 
make_field(nscat,
"number of scatterings") ;
 
   78    zap[
"i"] = 
make_field(interval,
"number of MCMC steps to take between saving paths") ;
 
   79    zap[
"b"] = 
make_field(burnIn,
"number of burn-in steps") ;
 
   80    zap[
"s"] = 
make_field(stepsize,
"step size for the MCMC steps") ;
 
   81    zap[
"sourceNB"] = 
make_field(sourceNB,
"Use a nanobeacon profile as source (currently a uniform distribution in a 45 degree cone around the positive z-direction") ;
 
   82    zap[
"target_zenith"] = 
make_field(target_zenith,
"[degrees] OPTIONAL: set to  use a realistic PMT acceptance") = -1 ;
 
   83 
   84    if (zap.
read(argc, argv) != 0) {
 
   85      return 1 ;
   86    }
   87  }
   88  catch(const exception &error) {
   89    
   90  }
   91 
   92  
   93  cout << "output file name   = '" << outfile << "'." << endl ;
   94  cout << "absorption length  = " << lA << " m" << endl ;
   95  cout << "distance to target = " << d  << " m" << endl ;
   96  cout << "npaths             = " << npaths << endl ;
   97  cout << "nscat              = " << nscat << endl ;
   98  cout << "interval           = " << interval << " steps" << endl ;
   99  cout << "burn-in            = " << burnIn << " steps" << endl ;
  100  cout << "step size          = " << stepsize << " m" << endl ;
  101  cout << endl ;
  102 
  103  
  105  cout << "Henyey-Greenstein scattering length = " << lHG << " m" << endl ;
  106  cout << "g = " << g << endl ;
  107  smHG.setScatteringLength(lHG) ;
  108  smHG.setScatteringProfileHG(g) ;
  109  cout << endl ;
  110 
  111  
  113  cout << "Rayleigh scattering length = " << lR << " m" << endl ;
  114  cout << 
"a = " << 
a << endl ;
 
  115  smR.setScatteringLength(lR) ;
  116  smR.setScatteringProfileRayleigh(a) ;
  117  cout << endl ;
  118 
  119  
  120  cout << "Combining HG and Rayleigh scattering into a single effective model." << endl ;
  122  setEffectiveScatteringModel( smHG, smR, sm ) ;
  124  sm.setAbsorptionLength(lA) ;
  125 
  126  cout << "Integral over scattering profile = " << sm.hscat->Integral("width")*2*M_PI << " (should be 1)" << endl ;
  127  cout << endl ;
  128 
  129  
  130  if( sourceNB ) {
  131    cout << "Setting source distribution to a preliminary approximation of a nanobeacon profile. Light is emitted uniformly within a cone around the positive z-axis." << endl ;
  132    
  134    for( Int_t xbin=1; xbin<=sm.hsource->GetNbinsX() ; ++xbin ) {
  135      double val = 0 ;
  136      double xmin = sm.hsource->GetXaxis()->GetBinLowEdge(bin) ;
 
  137      double xmax = sm.hsource->GetXaxis()->GetBinUpEdge(bin) ;
 
  138      for( 
int i=0 ; i<
n ; ++i ) {
 
  140        if( ct >= sqrt(0.5) ) val += 1 ;
  141      }
  143      for( Int_t ybin=1 ; ybin<=sm.hsource->GetNbinsY() ; ++ybin ) {
  144        Int_t bin = sm.hsource->GetBin(xbin,ybin) ;
  145        sm.hsource->SetBinContent(bin,val) ;
  146      }
  147    }
  148    sm.hsource->Scale( sqrt(2)/(2*M_PI*(sqrt(2)-1)) ) ;
  149    cout << endl ;
  150  }
  151 
  152  cout << "Integral over source profile = " << sm.hsource->Integral("width") << " (should be 1)" << endl ;
  153  cout << endl ;
  154 
  155  
  156  if( target_zenith >= 0 ) {
  157    cout << "Setting target to a KM3NeT PMT." << endl 
  158         << "Its orientation is rotated " << target_zenith << " degrees w.r.t. the negative z-axis" << endl
  159         << "(the rotation is in the yz-plane)" << endl ;
  160    target_zenith *= M_PI/180 ; 
  162    for( Int_t xbin=1; xbin<=sm.htarget->GetXaxis()->GetNbins() ; ++xbin ) {
  163      double ct = sm.htarget->GetXaxis()->GetBinCenter(xbin) ;
  164      double theta = acos(ct) ;
  165      for( Int_t ybin=1; ybin<=sm.htarget->GetYaxis()->GetNbins() ; ++ybin ) {
  166        Int_t bin = sm.htarget->GetBin(xbin,ybin) ;
  167        double phi = sm.htarget->GetYaxis()->GetBinCenter(ybin) ;
  168        
  170                                        sin(phi)*sin(theta), 
  171                                        cos(theta) ) ;
  172        double effct = -testdir.getDot(pmtdir) ;
  174        
  175        
  176        if( val == 0 ) val = 1e-10 ;
  177        sm.htarget->SetBinContent(bin,val) ;
  178      }
  179    }
  180    double maxval = sm.htarget->GetBinContent( sm.htarget->GetMaximumBin() ) ;
  181    sm.htarget->Scale(1.0/maxval) ;
  182    cout << endl ;
  183  }
  184 
  185  
  186  if( smoutfile != "" ) {
  187    cout << "Saving scattering model to '" << smoutfile << "'." << endl ;
  188    TFile* fout = new TFile(smoutfile.c_str(),"recreate") ;
  189    sm.Write() ;
  190    
  191    
  192    fout->mkdir("ScatteringModel_ingredients")->cd() ;
  193    sm.hsource->Write() ;
  194    sm.hscat->Write() ;
  195    sm.htarget->Write() ;
  196    fout->cd() ;
  197    fout->Close() ;
  198    cout << endl ;
  199  }
  200 
  201  
  202  cout << "Generating ensemble" << endl ;
  205  cout << "Done generating ensemble." << endl ;
  207  cout << 100*acceptance << "% of steps were accepted" << endl
  208       << "(as a rule of thumb, ~23% is optimal for high-dimensional spaces)" << endl 
  209       << endl ;
  210 
  211  
  212  cout << "Writing generated ensemble to '" << outfile << "'." << endl ;
  214  writer.
open(outfile.c_str()) ;
 
  217  }
  219  cout << endl ;
  220 
  221  cout << "Done!" << endl ;
  222 
  223  return 0 ;
  224}
#define make_field(A,...)
macro to convert parameter to JParserTemplateElement object
 
Data structure for normalised vector in three dimensions.
 
virtual void open(const char *file_name) override
Open file.
 
virtual void close()
Close file.
 
virtual bool put(const T &object)=0
Object output.
 
The JMarkovPathGenerator generates ensembles of photon paths using a Markov Chain Monte Carlo (MCMC).
 
std::vector< JPhotonPath > generateEnsemble(int n, const JPhotonPath &start_path, JSourceModel *src, JScatteringModel *sm, JTargetModel *trg, double lambda_abs, int nsteps_burn_in, int nsteps_save)
Generate an ensemble of n paths with a fixed number of scatterings by MCMC-sampling the given scatter...
 
double getFractionAccepted()
get the fraction of accepted steps during the last call to generateEnsemble (after burn-in)
 
Virtual base class for a scattering model.
 
virtual double getScatteringLength()
 
Utility class to parse command line options.
 
int read(const int argc, const char *const argv[])
Parse the program's command line options.
 
double getAngularAcceptance(const double x)
Get angular acceptance of PMT.