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.