Jpp  master_rocky-37-gf0c5bc59d
the software that should make you happy
Public Member Functions | Protected Member Functions | List of all members
FreePathSolver Class Reference

Finds photon paths from a nanobeacon source to a target PMT that have a non-zero probability. More...

Public Member Functions

 FreePathSolver ()
 
JPhotonPath solve (int nscat, const JDirectedSource *src, const JPMTTarget *trg)
 

Protected Member Functions

double sourceScore (const JPhotonPath &p, const JDirectedSource *src)
 
double targetScore (const JPhotonPath &p, const JPMTTarget *trg)
 
double intersectScore (const JPhotonPath &p, const JPMTTarget *trg)
 
double getScore (const JPhotonPath &p, const JDirectedSource *src, const JPMTTarget *trg)
 

Detailed Description

Finds photon paths from a nanobeacon source to a target PMT that have a non-zero probability.

This means that

It works by maximizing a score function. If we find a score of 0, the path meets all criteria.

Definition at line 162 of file JBeaconSimulator.cc.

Constructor & Destructor Documentation

◆ FreePathSolver()

FreePathSolver::FreePathSolver ( )
inline

Definition at line 165 of file JBeaconSimulator.cc.

165 {}

Member Function Documentation

◆ solve()

JPhotonPath FreePathSolver::solve ( int  nscat,
const JDirectedSource src,
const JPMTTarget trg 
)
inline

Definition at line 167 of file JBeaconSimulator.cc.

167  {
168  //cout << "Running FreePathSolver::solve with nscat = " << nscat << endl ;
169 
170  JPhotonPath p(min(2,nscat)) ;
171 
172  // start at source
173  p.front() = src->getPosition() ;
174  // end on PMT surface
175  p.back() = trg->getPosition() ;
176  if( trg->getRadius()>0 ) p.back() = trg->getPosition() + trg->getRadius() * JVector3D(trg->getDirection()) ;
177 
178  if( nscat == 0 ) return p ;
179 
180  // create intermediate points
181  for( int nv=1 ; nv<(int)p.size()-1 ; ++nv ) {
182  double factor = 1.0 * nv / (p.size()-1) ;
183  p[nv] = (1-factor)*p.front() + factor*p.back() ;
184  }
185 
186  int maxnsteps = -1 ;
187 
188  if( nscat == 1 ) {
189  double score = getScore(p,src,trg) ;
190  double dl = 1 ; // m
191  const double dlmin = 0.0001 ;
192  JPosition3D dx(1,0,0) ;
193  JPosition3D dy(0,1,0) ;
194  JPosition3D dz(0,0,1) ;
195  int istep = 0 ;
196  while( score<0 ) {
197  if( ++istep == maxnsteps ) break ;
198  double initscore = score ;
199 
200  // try step in x-direction
201  p[1] = p[1] + dl*dx ;
202  if( getScore(p,src,trg) < score ) {
203  // try moving in the opposite direction
204  p[1] = p[1] - 2*dl*dx ;
205  if( getScore(p,src,trg) < score ) p[1] = p[1] + dl*dx ;
206  }
207 
208  // try step in y-direction
209  p[1] = p[1] + dl*dy ;
210  if( getScore(p,src,trg) < score ) {
211  // try moving in the opposite direction
212  p[1] = p[1] - 2*dl*dy ;
213  if( getScore(p,src,trg) < score ) p[1] = p[1] + dl*dy ;
214  }
215 
216  // try step in z-direction
217  p[1] = p[1] + dl*dz ;
218  if( getScore(p,src,trg) < score ) {
219  // try moving in the opposite direction
220  p[1] = p[1] - 2*dl*dz ;
221  if( getScore(p,src,trg) < score ) p[1] = p[1] + dl*dz ;
222  }
223 
224  // see if it worked
225  score = getScore(p,src,trg) ;
226  // check if we are stuck
227  if( score == initscore ) {
228  dl = 0.5 * dl ;
229  //cout << "dl = " << dl << endl ;
230  if( dl<dlmin ) break ;
231  }
232  if( p.getLength() > 10000 ) break ;
233  }
234  }
235 
236  if( nscat>1) {
237  //cout << "nscat more than one" << endl ;
238  //cout << "starting with " << endl ;
239  //for( vector<JPosition3D>::iterator it=p.begin() ; it!= p.end() ; ++it ) cout << *it << endl ;
240  //cout << endl ;
241 
242  double score = getScore(p,src,trg) ;
243  double dl = 1 ; // m
244  const double dlmin = 1e-10 ;
245 
246  const int nsm = 6 ;
247  JPosition3D single_moves[nsm] = { JPosition3D(1,0,0), JPosition3D(0,1,0), JPosition3D(0,0,1),
248  JPosition3D(-1,0,0), JPosition3D(0,-1,0), JPosition3D(0,0,-1) } ;
249  /*ctor< pair<JPosition3D,JPosition3D> > moves ;
250  for( int i=0 ; i<nsm ; ++i ) {
251  for( int j=0 ; j<nsm ; ++j ) {
252  moves.push_back( pair<JPosition3D,JPosition3D>(single_moves[i],single_moves[j]) ) ;
253  }
254  }*/
255 
256  int i = 0 ;
257 
258  while( score<0 ) {
259  if( ++i>100 ) break ;
260  //cout << "@ " << JPosition3D(p[1]-src->getPosition()) << ", " << JPosition3D(p[2]-src->getPosition()) << ", score = " << score << ", dl = " << dl << endl ;
261  double initscore = score ;
262 
263  for( int i=0; i<nsm; ++i ) {
264  // try move
265  p[1] = p[1] + dl * single_moves[i] ;
266  double newscore = getScore(p,src,trg) ;
267  if( newscore < score ) {
268  // if the score is reduced, undo the move
269  p[1] = p[1] - dl * single_moves[i] ;
270  } else {
271  //cout << "First vertex adds " << single_moves[i]
272  // << ", score difference = " << newscore - score << endl ;
273  score = newscore ;
274  }
275  }
276 
277  for( int i=0; i<nsm; ++i ) {
278  // try move
279  p[2] = p[2] + dl * single_moves[i] ;
280  double newscore = getScore(p,src,trg) ;
281  if( newscore < score ) {
282  // if the score is reduced, undo the move
283  p[2] = p[2] - dl * single_moves[i] ;
284  } else {
285  //cout << "Second vertex adds " << single_moves[i]
286  // << ", score difference = " << newscore - score << endl ;
287  score = newscore ;
288  }
289  }
290 
291  // see if it worked
292  score = getScore(p,src,trg) ;
293  // check if we are stuck
294  if( score == initscore ) {
295  //cout << "Stuck" << endl ;
296  dl = 0.5*dl ;
297  if( dl<dlmin ) break ;
298  }
299  if( p.getLength() > 10000 ) {
300  //cout << "Too long" << endl ;
301  break ;
302  }
303  }
304 
305  // fill in the gaps
306  JPhotonPath p2(nscat) ;
307  p2[0] = p[0] ;
308  p2[1] = p[1] ;
309  p2[2] = p[2] ;
310  p2.back() = p.back() ;
311  for( int nv=3 ; nv<nscat+1 ; ++nv ) {
312  double factor = 1.0 * (nv-2) / (nscat-1) ;
313  p2[nv] = (1-factor)*p2[2] + factor*p2.back() ;
314  }
315  return p2 ;
316  }
317 
318  return p ;
319 
320  }
double getScore(const JPhotonPath &p, const JDirectedSource *src, const JPMTTarget *trg)
Data structure for position in three dimensions.
Definition: JPosition3D.hh:38
Data structure for vector in three dimensions.
Definition: JVector3D.hh:36
A photon path.
Definition: JPhotonPath.hh:38
const JPosition3D & getPosition() const
const JVersor3D & getDirection() const
const JPosition3D & getPosition() const

◆ sourceScore()

double FreePathSolver::sourceScore ( const JPhotonPath p,
const JDirectedSource src 
)
inlineprotected

Definition at line 324 of file JBeaconSimulator.cc.

324  {
325  double ct = JVersor3D(p[1]-src->getPosition()).getDot(src->getDirection()) ;
326  const double ctmin = cos(0.5*src->getOpeningAngle()) ;
327  double val = max(ctmin-ct,0.0) / (1-ctmin) ;
328  return -val*val ;
329  }
Data structure for normalised vector in three dimensions.
Definition: JVersor3D.hh:28
double getDot(const JVersor3D &versor) const
Get dot product.
Definition: JVersor3D.hh:156
JVersor3D getDirection() const
return the source direction
double getOpeningAngle() const
return the opening angle in radians

◆ targetScore()

double FreePathSolver::targetScore ( const JPhotonPath p,
const JPMTTarget trg 
)
inlineprotected

Definition at line 331 of file JBeaconSimulator.cc.

331  {
332  double ct = JVersor3D(p[p.size()-2]-p[p.size()-1]).getDot(trg->getDirection()) ;
333  const double ctmin = cos(0.5*trg->getOpeningAngle()) ;
334  double val = max(ctmin-ct,0.0) / (1-ctmin) ;
335  return -val*val ;
336  }
double getOpeningAngle() const
return the PMT opening angle in radians

◆ intersectScore()

double FreePathSolver::intersectScore ( const JPhotonPath p,
const JPMTTarget trg 
)
inlineprotected

Definition at line 338 of file JBeaconSimulator.cc.

338  {
339  double score = 0 ;
340 
341  // check whether the photon path goes through the target sphere
342  // we do not need to consider the last vertex, because if that intersects the sphere
343  // the target score would be 0.
344  if( p.n == 2 ) return score ;
345 
346  for( int nv=1 ; nv<(int)p.size()-2 ; ++nv ) {
347  JPhotonPath seg(0) ;
348  seg[0] = p[nv] ;
349  seg[1] = p[nv+1] ;
350  if( seg.hitsSphere(trg->getPosition(),trg->getRadius()) ) {
351  double d = JAxis3D( seg[0], JVersor3D(seg[1]-seg[0]) ).getDistance(trg->getPosition()) ;
352  double R = trg->getRadius() ;
353  double val = (R-d)/R ;
354  score -= val*val ;
355  //cout << "Segment from " << nv << " to " << nv+1 << "intersects sphere"
356  // << ", distance = " << d << ", val = " << val << endl ;
357  }
358  }
359 
360  /*JPhotonPath pshort(p) ;
361  pshort.resize( pshort.size()-1 ) ;
362  --pshort.n ;
363  if( pshort.hitsSphere(trg->getPosition(),trg->getRadius()) ) {
364  JVersor3D hit_dir( pshort.getSphereHitPosition(trg->getPosition(),trg->getRadius()) - trg->getPosition() ) ;
365  double val = hit_dir.getDot(trg->getDirection()) ;
366  score -= val * val ;
367  }
368 
369  // extra penalty when a vertex is inside the target
370  for( int nv=1 ; nv<p.n-1 ; ++nv ) {
371  double r = p[nv].getDistance(trg->getPosition()) ;
372  if( r < trg->getRadius() ) {
373  double val = ( trg->getRadius() - r ) / trg->getRadius() ;
374  score -= val * val ;
375  }
376  }*/
377 
378  return score ;
379  }
Axis object.
Definition: JAxis3D.hh:41
double getDistance(const JVector3D &pos) const
Get distance.
Definition: JAxis3D.hh:213

◆ getScore()

double FreePathSolver::getScore ( const JPhotonPath p,
const JDirectedSource src,
const JPMTTarget trg 
)
inlineprotected

Definition at line 382 of file JBeaconSimulator.cc.

382  {
383  double score = sourceScore(p,src) + targetScore(p,trg) + intersectScore(p,trg) ;
384  return score ;
385  }
double sourceScore(const JPhotonPath &p, const JDirectedSource *src)
double targetScore(const JPhotonPath &p, const JPMTTarget *trg)
double intersectScore(const JPhotonPath &p, const JPMTTarget *trg)

The documentation for this class was generated from the following file: