GENIEGenerator
Loading...
Searching...
No Matches
HNLVertexGenerator.cxx
Go to the documentation of this file.
1//____________________________________________________________________________
2/*
3 Copyright (c) 2003-2025, The GENIE Collaboration
4 For the full text of the license visit http://copyright.genie-mc.org
5
6 Author: John Plows <komninos-john.plows \at physics.ox.ac.uk>
7 University of Oxford
8*/
9//____________________________________________________________________________
10
12
13using namespace genie;
14using namespace genie::hnl;
15using namespace genie::units;
16
17//____________________________________________________________________________
19 GeomRecordVisitorI("genie::hnl::VertexGenerator")
20{
21
22}
23//____________________________________________________________________________
26{
27
28}
29//____________________________________________________________________________
30VertexGenerator::VertexGenerator(string name, string config) :
31 GeomRecordVisitorI(name, config)
32{
33
34}
35//____________________________________________________________________________
40//____________________________________________________________________________
42{
43 /*!
44 * Uses ROOT's TGeoManager to find out where the intersections with the detector volume live
45 * Label them as entry and exit point. Then use them to determine:
46 * 1) A decay vertex within the detector
47 * 2) A time-of-decay (== delay of HNL to reach the decay vertex wrt a massless SM v)
48 * 3) Geom weight: Survival to detector * decay within detector.
49 */
50
51 // before anything else: find the geometry!
52 if( !fGeoManager ){
53 LOG( "HNL", pINFO )
54 << "Getting geometry information from " << fGeomFile;
55
56 fGeoManager = TGeoManager::Import(fGeomFile.c_str());
57
58 TGeoVolume * top_volume = fGeoManager->GetTopVolume();
59 assert( top_volume );
60 TGeoShape * ts = top_volume->GetShape();
61 TGeoBBox * box = (TGeoBBox *) ts;
62
63 this->ImportBoundingBox(box);
64 }
65
66 this->SetStartingParameters( event_rec );
67
68 double weight = 1.0; // pure geom weight
69
70 TVector3 startPoint, momentum, entryPoint, exitPoint;
71 startPoint.SetXYZ( fSx, fSy, fSz );
72 momentum.SetXYZ( fPx, fPy, fPz );
73
74 bool didIntersectDet = this->VolumeEntryAndExitPoints( startPoint, momentum, entryPoint, exitPoint, fGeoManager, fGeoVolume );
75
76 if( isUsingDk2nu ) assert( didIntersectDet ); // forced to hit detector somewhere!
77 else {
78 std::vector< double > * newProdVtx = new std::vector< double >();
79 newProdVtx->emplace_back( startPoint.X() );
80 newProdVtx->emplace_back( startPoint.Y() );
81 newProdVtx->emplace_back( startPoint.Z() );
82
83 }
84 if( !didIntersectDet ){ // bail
85 LOG( "HNL", pERROR )
86 << "Bailing...";
87 TLorentzVector v4dummy( -999.9, -999.9, -999.9, -999.9 );
88 event_rec->SetVertex( v4dummy );
89 return;
90 }
91
92 this->EnforceUnits( "mm", "rad", "ns" );
93
94 // move fCoMLifetime to ns from GeV^{-1}
95 fCoMLifetime *= 1.0 / ( units::ns * units::GeV );
96
97 double maxDx = exitPoint.X() - entryPoint.X();
98 double maxDy = exitPoint.Y() - entryPoint.Y();
99 double maxDz = exitPoint.Z() - entryPoint.Z();
100
101 double maxLength = std::sqrt( std::pow( maxDx , 2.0 ) +
102 std::pow( maxDy , 2.0 ) +
103 std::pow( maxDz , 2.0 ) );
104
105 TLorentzVector * p4HNL = event_rec->Particle(0)->GetP4();
106 double betaMag = p4HNL->P() / p4HNL->E();
107 double gamma = std::sqrt( 1.0 / ( 1.0 - betaMag * betaMag ) );
108
109 double elapsed_length = this->CalcTravelLength( betaMag, fCoMLifetime, maxLength ); //mm
110 __attribute__((unused)) double ratio_length = elapsed_length / maxLength;
111
112 // from these we can also make the weight. It's P( survival ) * P( decay in detector | survival )
113 double distanceBeforeDet = std::sqrt( std::pow( (entryPoint.X() - startPoint.X()), 2.0 ) +
114 std::pow( (entryPoint.Y() - startPoint.Y()), 2.0 ) +
115 std::pow( (entryPoint.Y() - startPoint.Z()), 2.0 ) ); // mm
116
117 double timeBeforeDet = distanceBeforeDet / ( betaMag * kNewSpeedOfLight ); // ns lab
118 double timeInsideDet = maxLength / ( betaMag * kNewSpeedOfLight ); // ns lab
119
120 double LabToRestTime = 1.0 / ( gamma );
121 timeBeforeDet *= LabToRestTime; // ns rest
122 timeInsideDet *= LabToRestTime; // ns rest
123
124 double survProb = std::exp( - timeBeforeDet / fCoMLifetime );
125 weight *= 1.0 / survProb;
126 double decayProb = 1.0 - std::exp( - timeInsideDet / fCoMLifetime );
127 weight *= 1.0 / decayProb;
128
129 // save the survival and decay probabilities
130 if( event_rec->Particle(1) && event_rec->Particle(2) ){
131 event_rec->Particle(1)->SetPosition( 0.0, 0.0, 0.0, survProb );
132 event_rec->Particle(2)->SetPosition( 0.0, 0.0, 0.0, decayProb );
133 }
134
135 // update the weight
136 event_rec->SetWeight( event_rec->Weight() * weight );
137
138 TVector3 decayPoint = this->GetDecayPoint( elapsed_length, entryPoint, momentum ); // USER, mm
139
140 // write out vtx in [m, ns]
141 TLorentzVector x4( decayPoint.X() * units::mm / units::m,
142 decayPoint.Y() * units::mm / units::m,
143 decayPoint.Z() * units::mm / units::m,
144 event_rec->Vertex()->T() );
145
146 event_rec->SetVertex(x4);
147
148 // the validation app doesn't run the Decayer. So we will insert two neutrinos (not a valid
149 // decay mode), to store entry and exit point
150 if( !isUsingDk2nu ){
151 assert( !event_rec->Particle(1) );
152
153 TLorentzVector tmpp4( 0.0, 0.0, 0.0, 0.5 );
154 TLorentzVector ex4( 0.0, 0.0, 0.0, 0.0 );
155 ex4.SetXYZT( entryPoint.X(), entryPoint.Y(), entryPoint.Z(), 0.0 );
156 TLorentzVector xx4( 0.0, 0.0, 0.0, 0.0 );
157 xx4.SetXYZT( exitPoint.X(), exitPoint.Y(), exitPoint.Z(), 0.0 );
158
159 GHepParticle nu1( genie::kPdgNuMu, kIStStableFinalState, -1, -1, -1, -1, tmpp4, ex4 );
160 GHepParticle nu2( genie::kPdgAntiNuMu, kIStStableFinalState, -1, -1, -1, -1, tmpp4, xx4 );
161
162 event_rec->AddParticle( nu1 ); event_rec->AddParticle( nu2 );
163
164 // save the survival and decay probabilities
165 // event_rec->Particle(1)->SetPolarization( survProb, decayProb );
166 event_rec->Particle(1)->SetPosition( 0.0, 0.0, 0.0, survProb );
167 event_rec->Particle(2)->SetPosition( 0.0, 0.0, 0.0, decayProb );
168 event_rec->SetWeight(weight);
169 }
170
171 // also set entry and exit points. Do this in x4 of Particles(1,2)
172 if( event_rec->Particle(1) && event_rec->Particle(2) ){
173 (event_rec->Particle(1))->SetPosition( entryPoint.X(), entryPoint.Y(), entryPoint.Z(), event_rec->Particle(1)->Vt() );
174 (event_rec->Particle(2))->SetPosition( exitPoint.X(), exitPoint.Y(), exitPoint.Z(), event_rec->Particle(2)->Vt() );
175 }
176
177}
178//____________________________________________________________________________
179void VertexGenerator::EnforceUnits( std::string length_units, std::string angle_units, std::string time_units ) const{
180
181 LOG( "HNL", pWARN )
182 << "Switching units to " << length_units.c_str() << " , " << angle_units.c_str() << " , " << time_units.c_str();
183
184 double old_lunits = lunits;
185 __attribute__((unused)) double old_aunits = aunits;
186 double old_tunits = tunits;
187
188 lunits = utils::units::UnitFromString( length_units ); lunitString = length_units;
189 aunits = utils::units::UnitFromString( angle_units );
190 tunits = utils::units::UnitFromString( time_units ); tunitString = time_units;
191
192 // convert to new units
193 fSx /= lunits/old_lunits; fSy /= lunits/old_lunits; fSz /= lunits/old_lunits;
194 fPx /= lunits/old_lunits; fPy /= lunits/old_lunits; fPz /= lunits/old_lunits;
195 fEx /= lunits/old_lunits; fEy /= lunits/old_lunits; fEz /= lunits/old_lunits;
196 fXx /= lunits/old_lunits; fXy /= lunits/old_lunits; fXz /= lunits/old_lunits;
197 fLx /= lunits/old_lunits; fLy /= lunits/old_lunits; fLz /= lunits/old_lunits;
198
199 fDx /= lunits/old_lunits; fDy /= lunits/old_lunits; fDz /= lunits/old_lunits;
200 fOx /= lunits/old_lunits; fOy /= lunits/old_lunits; fOz /= lunits/old_lunits;
201
202 kNewSpeedOfLight /= (lunits / old_lunits) / (tunits / old_tunits);
203
204 LOG( "HNL", pDEBUG )
205 << "kNewSpeedOfLight = " << kNewSpeedOfLight << " [" << lunitString.c_str() << "/"
206 << tunitString.c_str() << "]";
207}
208//____________________________________________________________________________
209double VertexGenerator::CalcTravelLength( double betaMag, double CoMLifetime, double maxLength ) const
210{
211 // decay probability P0(t) = 1 - exp( -t/tau ) where:
212 // t = time-of-flight (in rest frame)
213 // tau = CoMLifetime
214
215 assert( betaMag > 0.0 && betaMag < 1.0 ); // massive moving particle
216 double maxLabTime = maxLength / ( betaMag * kNewSpeedOfLight );
217 double gamma = std::sqrt( 1.0 / ( 1.0 - betaMag * betaMag ) );
218 double maxRestTime = maxLabTime / gamma ; // this is how "wide" the detector looks like
219
220 // if P(DL=0) = 1, P(DL = LMax) = exp( - LMax / c * 1/( beta * gamma ) * 1 / CoMLifetime )
221 double PExit = std::exp( - maxRestTime / CoMLifetime );
222
223 // from [0,1] we'd reroll anything in [0, PExit] and keep (PExit, 1]. That's expensive.
224 // Instead, let 1 ==> maxRestTime, 0 ==> 0, exponential decay
225
227 double ranthrow = rnd->RndGen().Uniform();
228
229 double S0 = (1.0 - PExit) * ranthrow + PExit;
230 double rest_time = CoMLifetime * std::log( 1.0 / S0 );
231 double elapsed_time = rest_time * gamma;
232 double elapsed_length = elapsed_time * betaMag * kNewSpeedOfLight;
233
234 /*
235 LOG( "HNL", pDEBUG )
236 << "betaMag, maxLength, CoMLifetime = " << betaMag << ", " << maxLength << ", " << CoMLifetime
237 << "\nbetaMag = " << betaMag << " ==> gamma = " << gamma
238 << "\n==> maxLength [" << tunitString.c_str()
239 << "] = " << maxRestTime << " (rest frame) = " << maxLabTime << " (lab frame)"
240 << "\nranthrow = " << ranthrow << ", PExit = " << PExit
241 << "\n==> S0 = " << S0 << " ==> rest_time [" << lunitString.c_str() << "] = " << rest_time
242 << " ==> elapsed_time [" << tunitString.c_str()
243 << "] = " << elapsed_time << " ==> elapsed_length [" << lunitString.c_str()
244 << "] = " << elapsed_length;
245 */
246
247 return elapsed_length;
248}
249//____________________________________________________________________________
250TVector3 VertexGenerator::GetDecayPoint( double travelLength, TVector3 & entryPoint, TVector3 & momentum ) const
251{
252 double ex = entryPoint.X(); double ey = entryPoint.Y(); double ez = entryPoint.Z();
253 double px = momentum.X(); double py = momentum.Y(); double pz = momentum.Z();
254 double p2 = px*px + py*py + pz*pz; double p = std::sqrt(p2);
255 px *= 1./p; py *= 1./p; pz *= 1./p;
256
257 double dx = ex + travelLength * px; fDx = dx;
258 double dy = ey + travelLength * py; fDy = dy;
259 double dz = ez + travelLength * pz; fDz = dz;
260
264
265 TVector3 decayPoint( dx, dy, dz );
266 return decayPoint;
267}
268//____________________________________________________________________________
269double VertexGenerator::GetMaxLength( TVector3 & entryPoint, TVector3 & exitPoint ) const
270{
271 double ex = entryPoint.X(); double ey = entryPoint.Y(); double ez = entryPoint.Z();
272 double xx = exitPoint.X(); double xy = exitPoint.Y(); double xz = exitPoint.Z();
273
274 return std::sqrt( (ex-xx)*(ex-xx) + (ey-xy)*(ey-xy) + (ez-xz)*(ez-xz) );
275}
276//____________________________________________________________________________
278{
279 fOx = 0.0; fOy = 0.0; fOz = 0.0;
280 fLx = 1.0; fLy = 1.0; fLz = 1.0; // m
281
285
289
290 LOG("HNL", pDEBUG)
291 << "Setting simple decay volume with unit-m side."
292 << "\nSetting units to \"mm\", \"rad\", \"ns\"";
293
294 EnforceUnits("mm","rad","ns");
295}
296//____________________________________________________________________________
297// if entry and exit points, populate TVector3's with their coords. If not, return false
298bool VertexGenerator::SDVEntryAndExitPoints( TVector3 & startPoint, TVector3 momentum,
299 TVector3 & entryPoint, TVector3 & exitPoint ) const
300{
301 assert( fOx == 0.0 && fOy == 0.0 && fOz == 0.0 &&
302 fLx == 1000.0 && fLy == 1000.0 && fLz == 1000.0 ); // SDV, mm
303 fSx = startPoint.X(); fSy = startPoint.Y(); fSz = startPoint.Z(); // mm
304 fPx = momentum.X(); fPy = momentum.Y(); fPz = momentum.Z(); // GeV
305 double fP2 = fPx*fPx + fPy*fPy + fPz*fPz; double fP = std::sqrt(fP2); // GeV
306 fPx *= 1.0/fP; fPy *= 1.0/fP; fPz *= 1.0/fP; // GeV / GeV
307
308 // calc parameter for line at each face [mm]
309 double txP = ( fLx - fSx ) / fPx;
310 double txM = ( -fLx - fSx ) / fPx;
311 double tyP = ( fLy - fSy ) / fPy;
312 double tyM = ( -fLy - fSy ) / fPy;
313 double tzP = ( fLz - fSz ) / fPz;
314 double tzM = ( -fLz - fSz ) / fPz;
315
316 // do we have an entry or exit anywhere?
317 // entry from face Q = const <==> { pr(momentum, Q) points to origin && within bounding square }
318 // exit from face Q = const <==> { -pr(momentum, Q) points to origin && within bounding square }
319 double q1t = 0.0, q2t = 0.0;
320 bool pointsOnX = false, pointsOnY = false, pointsOnZ = false;
321
322 // case x = +fLx
323 q1t = fSy + txP * fPy; q2t = fSz + txP * fPz;
324 if( std::abs( q1t ) <= fLy && std::abs( q2t ) <= fLz ){ // within bounding square
325 pointsOnX = true;
326 if( fSx * fPx < 0 ){ // pointing towards origin
327 fEx = fLx; fEy = q1t; fEz = q2t;
328 } else if( fSx * fPx > 0 ){ // pointing away from origin
329 fXx = fLx; fXy = q1t; fXz = q2t;
330 } else return false; // treat tangent as no entry
331 }
332 // case x = -fLx
333 q1t = fSy + txM * fPy; q2t = fSz + txM * fPz;
334 if( std::abs( q1t ) <= fLy && std::abs( q2t ) <= fLz ){ // within bounding square
335 pointsOnX = true;
336 if( fSx * fPx < 0 ){ // pointing towards origin
337 fEx = -fLx; fEy = q1t; fEz = q2t;
338 } else if( fSx * fPx > 0 ){ // pointing away from origin
339 fXx = -fLx; fXy = q1t; fXz = q2t;
340 } else return false; // treat tangent as no entry
341 }
342
343 // case y = +fLy
344 q1t = fSz + tyP * fPz; q2t = fSx + tyP * fPx;
345 if( std::abs( q1t ) <= fLz && std::abs( q2t ) <= fLx ){ // within bounding square
346 pointsOnY = true;
347 if( fSy * fPy < 0 ){ // pointing towards origin
348 fEx = q2t; fEy = fLy; fEz = q1t;
349 } else if( fSy * fPy > 0 ){ // pointing away from origin
350 fXx = q2t; fXy = fLy; fXz = q1t;
351 } else return false; // treat tangent as no entry
352 }
353 // case y = -fLy
354 q1t = fSz + tyM * fPz; q2t = fSx + tyM * fPx;
355 if( std::abs( q1t ) <= fLz && std::abs( q2t ) <= fLx ){ // within bounding square
356 pointsOnY = true;
357 if( fSy * fPy < 0 ){ // pointing towards origin
358 fEx = q2t; fEy = -fLy; fEz = q1t;
359 } else if( fSy * fPy > 0 ){ // pointing away from origin
360 fXx = q2t; fXy = -fLy; fXz = q1t;
361 } else return false; // treat tangent as no entry
362 }
363
364 // case z = +fLz
365 q1t = fSx + tzP * fPx; q2t = fSy + tzP * fPy;
366 if( std::abs( q1t ) <= fLx && std::abs( q2t ) <= fLy ){ // within bounding square
367 pointsOnZ = true;
368 if( fSz * fPz < 0 ){ // pointing towards origin
369 fEx = q1t; fEy = q2t; fEz = fLz;
370 } else if( fSz * fPz > 0 ){ // pointing away from origin
371 fXx = q1t; fXy = q2t; fXz = fLz;
372 } else return false; // treat tangent as no entry
373 }
374 // case z = -fLz
375 q1t = fSx + tzM * fPx; q2t = fSy + tzM * fPy;
376 if( std::abs( q1t ) <= fLx && std::abs( q2t ) <= fLy ){ // within bounding square
377 pointsOnZ = true;
378 if( fSz * fPz < 0 ){ // pointing towards origin
379 fEx = q1t; fEy = q2t; fEz = -fLz;
380 } else if( fSz * fPz > 0 ){ // pointing away from origin
381 fXx = q1t; fXy = q2t; fXz = -fLz;
382 } else return false; // treat tangent as no entry
383 }
384
385 bool finalPoints = ( pointsOnX || pointsOnY || pointsOnZ );
386 if( finalPoints ){
387 entryPoint.SetXYZ( fEx, fEy, fEz );
388 exitPoint.SetXYZ( fXx, fXy, fXz );
389 return true;
390 }
391
392 // missed detector
393 return false;
394}
395//____________________________________________________________________________
396#ifdef __GENIE_GEOM_DRIVERS_ENABLED__
397void VertexGenerator::ImportBoundingBox( TGeoBBox * box ) const
398{
399 fLx = box->GetDX() * units::cm / lunits;
400 fLy = box->GetDY() * units::cm / lunits;
401 fLz = box->GetDZ() * units::cm / lunits;
402 fOx = (box->GetOrigin())[0] * units::cm / lunits;
403 fOy = (box->GetOrigin())[1] * units::cm / lunits;
404 fOz = (box->GetOrigin())[2] * units::cm / lunits;
405
406 fLxROOT = box->GetDX();
407 fLyROOT = box->GetDY();
408 fLzROOT = box->GetDZ();
409
410 fOxROOT = (box->GetOrigin())[0];
411 fOyROOT = (box->GetOrigin())[1];
412 fOzROOT = (box->GetOrigin())[2];
413}
414//____________________________________________________________________________
416{
417 isUsingDk2nu = (event_rec->Particle(1) != NULL); // validation App doesn't run Decayer
418 isUsingRootGeom = true;
419
421 xMult = ( isUsingDk2nu ) ? units::cm / units::mm : 1.0;
422
423 fCoMLifetime = event_rec->Probability();
424
425 assert( event_rec->Particle(0) );
426
427 TVector3 dumori(0.0, 0.0, 0.0); // tgt-hall frame origin is 0
428 TVector3 detori( (fCx + fDetTranslation.at(0)) * units::m / units::cm,
430 (fCz + fDetTranslation.at(2)) * units::m / units::cm ); // for rotations of the detector
431
432 TLorentzVector * x4HNL = event_rec->Particle(0)->GetX4(); // NEAR, cm ns
433 TVector3 xHNL_near = x4HNL->Vect();
434 TVector3 xHNL_user = this->ApplyUserRotation( xHNL_near, detori, fDetRotation, false ); // tgt-hall --> user
435 TLorentzVector * x4HNL_user = new TLorentzVector();
436 x4HNL_user->SetXYZT( xHNL_user.X() - (fCx + fDetTranslation.at(0)) * units::m / units::cm,
437 xHNL_user.Y() - (fCy + fDetTranslation.at(1)) * units::m / units::cm,
438 xHNL_user.Z() - (fCz + fDetTranslation.at(2)) * units::m / units::cm,
439 x4HNL->T() ); // USER, cm ns
440
441 TVector3 startPoint( xMult * x4HNL_user->X(), xMult * x4HNL_user->Y(), xMult * x4HNL_user->Z() ); // USER mm
442 double mtomm = units::m / units::mm;
443
444 TLorentzVector * p4HNL = event_rec->Particle(0)->GetP4();
445 TVector3 momentum( p4HNL->Px(), p4HNL->Py(), p4HNL->Pz() );
446
447
448 fSx = startPoint.X(); fSy = startPoint.Y(); fSz = startPoint.Z();
452 fPx = momentum.X(); fPy = momentum.Y(); fPz = momentum.Z();
453}
454//____________________________________________________________________________
455bool VertexGenerator::VolumeEntryAndExitPoints( TVector3 & startPoint, TVector3 & momentum,
456 TVector3 & entryPoint, TVector3 & exitPoint,
457 TGeoManager * /* gm */, TGeoVolume * /* vol */ ) const
458{
459 const double mmtolunits = units::mm / lunits;
460
461 double sx = startPoint.X(); double sy = startPoint.Y(); double sz = startPoint.Z();
462 sx *= mmtolunits; sy *= mmtolunits; sz *= mmtolunits;
463 double px = momentum.X(); double py = momentum.Y(); double pz = momentum.Z();
464 double p2 = px*px + py*py + pz*pz; double p = std::sqrt(p2);
465 px *= 1./p; py *= 1./p; pz *= 1./p;
466
467 fSx = sx; fSy = sy; fSz = sz;
469 fPx = px; fPy = py; fPz = pz;
470
471 // put first point slightly inside the bounding box
472 double firstZOffset = -0.1; // cm
473 firstZOffset *= units::cm / lunits;
474
475 double firstZ = fOz - (fLz/2.0 - firstZOffset);
476
477 // now find which point the line would hit this z at
478 double dz = firstZ - sz;
479 double tz = dz / pz;
480 double dx = tz * px;
481 double dy = tz * py;
482 double firstX = sx + dx;
483 double firstY = sy + dy;
484
485 // now we gotta return everything to cm for ROOT to work its magic.
486 double firstXROOT = firstX * lunits / units::cm,
487 firstYROOT = firstY * lunits / units::cm, firstZROOT = firstZ * lunits / units::cm;
488
489 if( !gGeoManager )
490 TGeoManager * gm = TGeoManager::Import(fGeomFile.c_str());
491 gGeoManager->SetCurrentPoint( firstXROOT, firstYROOT, firstZROOT );
492 gGeoManager->SetCurrentDirection( px, py, pz );
493
494 /*
495 LOG( "HNL", pINFO )
496 << "\nCurrent point is: ( " << firstX << ", " << firstY << ", " << firstZ << " ) [" << lunitString.c_str() << "]"
497 << "\nFrom start point : ( " << sx << ", " << sy << ", " << sz << " ) [" << lunitString.c_str() << "]"
498 << "\nIn ROOT, current is : ( " << firstXROOT << ", " << firstYROOT << ", " << firstZROOT << " ) [cm]"
499 << "\nIn ROOT, start is : ( " << fSxROOT << ", " << fSyROOT << ", " << fSzROOT << " ) [cm]"
500 << "\nCurrent direction is: ( " << px << ", " << py << ", " << pz << " ) [GeV/GeV]";
501 */
502
503 std::string pathString = this->CheckGeomPoint( firstXROOT, firstYROOT, firstZROOT );
504
505 assert( pathString.find("/", 1) == string::npos ); // need to be in TOP volume but outside any other volume so we can enter this.
506
507 double stepmax = 1.0e+6; // cm
508 stepmax *= genie::units::cm / lunits;
509
510 LOG( "HNL", pDEBUG )
511 << "Starting to search for intersections...";
512
513 // enter the volume.
514 TGeoNode * nextNode = gGeoManager->FindNextBoundaryAndStep( stepmax );
515
516 if( (gGeoManager->GetCurrentPoint())[0] == firstXROOT &&
517 (gGeoManager->GetCurrentPoint())[1] == firstYROOT &&
518 (gGeoManager->GetCurrentPoint())[2] == firstZROOT )
519 nextNode = gGeoManager->FindNextBoundaryAndStep();
520
521 pathString = this->CheckGeomPoint( (gGeoManager->GetCurrentPoint())[0],
522 (gGeoManager->GetCurrentPoint())[1],
523 (gGeoManager->GetCurrentPoint())[2] );
524
525 if( nextNode == NULL )
526 return false;
527
528 TVector3 dumori(0.0, 0.0, 0.0);
529
530 // entered the detector, let's save this point
531 fEx = ( gGeoManager->GetCurrentPoint() )[0] * genie::units::cm / lunits;
532 fEy = ( gGeoManager->GetCurrentPoint() )[1] * genie::units::cm / lunits;
533 fEz = ( gGeoManager->GetCurrentPoint() )[2] * genie::units::cm / lunits;
534 entryPoint.SetXYZ( fEx, fEy, fEz );
535
536 fExROOT = ( gGeoManager->GetCurrentPoint() )[0];
537 fEyROOT = ( gGeoManager->GetCurrentPoint() )[1];
538 fEzROOT = ( gGeoManager->GetCurrentPoint() )[2];
539
540 TVector3 entryPoint_user( fExROOT * units::cm / units::m,
542 fEzROOT * units::cm / units::m ); // USER, m
543 TVector3 entryPoint_near = this->ApplyUserRotation( entryPoint_user, dumori, fDetRotation, true );
544 entryPoint_near.SetXYZ( entryPoint_near.X() + (fCx + fDetTranslation.at(0)),
545 entryPoint_near.Y() + (fCy + fDetTranslation.at(1)),
546 entryPoint_near.Z() + (fCz + fDetTranslation.at(2)) );
547
548 /*
549 LOG( "HNL", pDEBUG )
550 << "\nEntry point found at ( " << fEx << ", " << fEy << ", " << fEz << " ) [" << lunitString.c_str() << "]"
551 << "\nIn ROOT, entry at ( " << fExROOT << ", " << fEyROOT << ", " << fEzROOT << " ) [cm]";
552 */
553
554 // now propagate until we exit again
555
556 int bdIdx = 0;
557 const int bdIdxMax = 1e+4;
558
559 double sfx = 0.0, sfy = 0.0, sfz = 0.0; // coords of the "safe" points in user units
560 double sfxROOT = 0.0, sfyROOT = 0.0, sfzROOT = 0.0; // same, in cm
561
562 // do one big step first
563 // then if not outside yet, step by ever smaller steps until some threshold
564 Double_t sNext = std::min( std::max( fLx, std::max( fLy, fLz ) ), 10.0 * lunits / units::cm ) / 2.0;
565 Double_t sNextROOT = sNext * lunits / units::cm;
566 gGeoManager->SetStep( sNextROOT );
567 gGeoManager->Step();
568
569 // FindNextBoundaryAndStep() sets step size to distance to next boundary and executes that step
570 // so one "step" here is actually one big step + one small step
571 while( gGeoManager->FindNextBoundaryAndStep() && bdIdx < bdIdxMax ){
572 const Double_t * currPoint = gGeoManager->GetCurrentPoint();
573
574 sfxROOT = currPoint[0]; sfyROOT = currPoint[1]; sfzROOT = currPoint[2];
575 if( sNextROOT >= 2.0 * lunits / units::cm ) sNextROOT *= 0.5;
576 gGeoManager->SetStep( sNextROOT );
577 gGeoManager->Step();
578 bdIdx++;
579 }
580 if( bdIdx == bdIdxMax ){
581 LOG( "HNL", pWARN )
582 << "Failed to exit this volume. Dropping this trajectory.";
583 return false;
584 }
585
586 // guard against small detectors
587 if( ( sfxROOT == 0.0 && sfyROOT == 0.0 && sfzROOT == 0.0 ) ||
588 ( sfxROOT == fExROOT && sfyROOT == fEyROOT && sfzROOT == fEzROOT ) ){
589 // set this to go 5 cm after the start.
590 LOG( "HNL", pWARN )
591 << "This section is smaller than 5 cm. Are you sure you want this decay volume? Proceeding anyway.";
592 gGeoManager->SetCurrentPoint( fExROOT, fEyROOT, fEzROOT );
593 gGeoManager->SetStep( 5.0 ); // ROOT units are cm!
594 gGeoManager->Step();
595 const Double_t * currPoint = gGeoManager->GetCurrentPoint();
596 sfxROOT = currPoint[0]; sfyROOT = currPoint[1]; sfzROOT = currPoint[2];
597 }
598
599 sfx = sfxROOT * units::cm / lunits; sfy = sfyROOT * units::cm / lunits; sfz = sfzROOT * units::cm / lunits;
600
601 // exited the detector, let's save this point
602 fXx = sfx; fXxROOT = sfxROOT;
603 fXy = sfy; fXyROOT = sfyROOT;
604 fXz = sfz; fXzROOT = sfzROOT;
605 exitPoint.SetXYZ( fXx, fXy, fXz );
606
607 TVector3 exitPoint_user( fXxROOT * units::cm / units::m,
609 fXzROOT * units::cm / units::m ); // USER, m
610 TVector3 exitPoint_near = this->ApplyUserRotation( exitPoint_user, dumori, fDetRotation, true );
611 exitPoint_near.SetXYZ( exitPoint_near.X() + (fCx + fDetTranslation.at(0)),
612 exitPoint_near.Y() + (fCy + fDetTranslation.at(1)),
613 exitPoint_near.Z() + (fCz + fDetTranslation.at(2)) );
614
615 /*
616 LOG( "HNL", pINFO )
617 << "\nExit point found at ( " << fXx << ", " << fXy << ", " << fXz << " ) ["
618 << lunitString.c_str() << "]"
619 << "\nIn ROOT, exit at ( " << fXxROOT << ", " << fXyROOT << ", " << fXzROOT << " ) [cm]";
620 */
621
622 return true;
623
624}
625#endif // #ifdef __GENIE_GEOM_DRIVERS_ENABLED__
626//____________________________________________________________________________
628{
629 Algorithm::Configure(config);
630 this->LoadConfig();
631}
632//____________________________________________________________________________
633void VertexGenerator::Configure(string config)
634{
635 Algorithm::Configure(config);
636 this->LoadConfig();
637}
638//____________________________________________________________________________
640{
641 if( fIsConfigLoaded ) return;
642
643 LOG( "HNL", pDEBUG )
644 << "Loading geometry parameters from file. . .";
645
646 this->GetParamVect( "Near2User_T", fB2UTranslation );
647 this->GetParamVect( "Near2User_R", fDetRotation );
648 this->GetParamVect( "Near2Beam_R", fB2URotation );
649 this->GetParamVect( "DetCentre_User", fDetTranslation );
650 fCx = fB2UTranslation.at(0); fCy = fB2UTranslation.at(1); fCz = fB2UTranslation.at(2);
651 fUx = fDetTranslation.at(0); fUy = fDetTranslation.at(1); fUz = fDetTranslation.at(2);
652 fAx1 = fB2URotation.at(0); fAz = fB2URotation.at(1); fAx2 = fB2URotation.at(2);
653 fBx1 = fDetRotation.at(0); fBz = fDetRotation.at(1); fBx2 = fDetRotation.at(2);
654
655 fIsConfigLoaded = true;
656}
657//____________________________________________________________________________
658void VertexGenerator::GetInterestingPoints( TVector3 & entryPoint, TVector3 & exitPoint, TVector3 & decayPoint ) const
659{
660 entryPoint.SetXYZ( fEx, fEy, fEz );
661 exitPoint.SetXYZ( fXx, fXy, fXz );
662 decayPoint.SetXYZ( fDx, fDy, fDz );
663}
664//____________________________________________________________________________
665TVector3 VertexGenerator::ApplyUserRotation( TVector3 vec, bool doBackwards ) const
666{
667 double vx = vec.X(), vy = vec.Y(), vz = vec.Z();
668
669 double Ax2 = ( doBackwards ) ? -fAx2 : fAx2;
670 double Az = ( doBackwards ) ? -fAz : fAz;
671 double Ax1 = ( doBackwards ) ? -fAx1 : fAx1;
672
673 // Ax2 first
674 double x = vx, y = vy, z = vz;
675 vy = y * std::cos( Ax2 ) - z * std::sin( Ax2 );
676 vz = y * std::sin( Ax2 ) + z * std::cos( Ax2 );
677 y = vy; z = vz;
678 // then Az
679 vx = x * std::cos( Az ) - y * std::sin( Az );
680 vy = x * std::sin( Az ) + y * std::cos( Az );
681 x = vx; y = vy;
682 // Ax1 last
683 vy = y * std::cos( Ax1 ) - z * std::sin( Ax1 );
684 vz = y * std::sin( Ax1 ) + z * std::cos( Ax1 );
685
686 TVector3 nvec( vx, vy, vz );
687 return nvec;
688}
689//____________________________________________________________________________
690TVector3 VertexGenerator::ApplyUserRotation( TVector3 vec, TVector3 oriVec, std::vector<double> rotVec, bool doBackwards ) const
691{
692 double vx = vec.X(), vy = vec.Y(), vz = vec.Z();
693 double ox = oriVec.X(), oy = oriVec.Y(), oz = oriVec.Z();
694
695 vx -= ox; vy -= oy; vz -= oz; // make this rotation about detector origin
696
697 assert( rotVec.size() == 3 ); // want 3 Euler angles, otherwise this is unphysical.
698 double Ax2 = ( doBackwards ) ? -rotVec.at(2) : rotVec.at(2);
699 double Az = ( doBackwards ) ? -rotVec.at(1) : rotVec.at(1);
700 double Ax1 = ( doBackwards ) ? -rotVec.at(0) : rotVec.at(0);
701
702 // Ax2 first
703 double x = vx, y = vy, z = vz;
704 vy = y * std::cos( Ax2 ) - z * std::sin( Ax2 );
705 vz = y * std::sin( Ax2 ) + z * std::cos( Ax2 );
706 y = vy; z = vz;
707 // then Az
708 vx = x * std::cos( Az ) - y * std::sin( Az );
709 vy = x * std::sin( Az ) + y * std::cos( Az );
710 x = vx; y = vy;
711 // Ax1 last
712 vy = y * std::cos( Ax1 ) - z * std::sin( Ax1 );
713 vz = y * std::sin( Ax1 ) + z * std::cos( Ax1 );
714
715 // back to beam frame
716 vx += ox; vy += oy; vz += oz;
717 TVector3 nvec( vx, vy, vz );
718 return nvec;
719}
720//____________________________________________________________________________
721void VertexGenerator::SetGeomFile( string geomfile ) const
722{
723 fGeomFile = geomfile;
724}
725//____________________________________________________________________________
726std::string VertexGenerator::CheckGeomPoint( Double_t x, Double_t y, Double_t z ) const
727{
728 Double_t point[3];
729 Double_t local[3];
730 point[0] = x;
731 point[1] = y;
732 point[2] = z;
733 TGeoVolume *vol = gGeoManager->GetTopVolume();
734 TGeoNode *node = gGeoManager->FindNode(point[0], point[1], point[2]);
735 gGeoManager->MasterToLocal(point, local);
736 return gGeoManager->GetPath();
737}
#define pINFO
Definition Messenger.h:62
#define pERROR
Definition Messenger.h:59
#define pDEBUG
Definition Messenger.h:63
#define LOG(stream, priority)
A macro that returns the requested log4cpp::Category appending a string (using the FILE,...
Definition Messenger.h:96
#define pWARN
Definition Messenger.h:60
int GetParamVect(const std::string &comm_name, std::vector< T > &v, bool is_top_call=true) const
Handle to load vectors of parameters.
virtual void Configure(const Registry &config)
Definition Algorithm.cxx:62
STDHEP-like event record entry that can fit a particle or a nucleus.
void SetPosition(const TLorentzVector &v4)
TLorentzVector * GetP4(void) const
TLorentzVector * GetX4(void) const
double Vt(void) const
Get production time.
GENIE's GHEP MC event record.
Definition GHepRecord.h:45
virtual double Weight(void) const
Definition GHepRecord.h:124
virtual double Probability(void) const
Definition GHepRecord.h:125
virtual void AddParticle(const GHepParticle &p)
virtual TLorentzVector * Vertex(void) const
Definition GHepRecord.h:140
virtual void SetWeight(double wght)
Definition GHepRecord.h:130
virtual void SetVertex(double x, double y, double z, double t)
virtual GHepParticle * Particle(int position) const
A singleton holding random number generator classes. All random number generation in GENIE should tak...
Definition RandomGen.h:29
static RandomGen * Instance()
Access instance.
Definition RandomGen.cxx:74
TRandom3 & RndGen(void) const
rnd number generator for generic usage
Definition RandomGen.h:80
A registry. Provides the container for algorithm configuration parameters.
Definition Registry.h:65
void Configure(const Registry &config)
TVector3 GetDecayPoint(double travelLength, TVector3 &entryPoint, TVector3 &momentum) const
void GetInterestingPoints(TVector3 &entryPoint, TVector3 &exitPoint, TVector3 &decayPoint) const
void SetGeomFile(std::string geomfile) const
double GetMaxLength(TVector3 &entryPoint, TVector3 &exitPoint) const
void SetStartingParameters(GHepRecord *event_rec) const
TVector3 ApplyUserRotation(TVector3 vec, bool doBackwards) const
bool SDVEntryAndExitPoints(TVector3 &startPoint, TVector3 momentum, TVector3 &entryPoint, TVector3 &exitPoint) const
void EnforceUnits(std::string length_units, std::string angle_units, std::string time_units) const
std::vector< double > fB2UTranslation
double CalcTravelLength(double betaMag, double CoMLifetime, double maxLength) const
std::vector< double > fDetTranslation
std::string CheckGeomPoint(Double_t x, Double_t y, Double_t z) const
std::vector< double > fDetRotation
std::vector< double > fB2URotation
void ProcessEventRecord(GHepRecord *event_rec) const
double CoMLifetime
string lunits
const double e
Physical System of Units.
static constexpr double cm
Definition Units.h:68
static constexpr double m
Definition Units.h:71
static constexpr double ns
Definition Units.h:98
static constexpr double kSpeedOfLight
Definition Units.h:32
static constexpr double GeV
Definition Units.h:28
static constexpr double mm
Definition Units.h:65
static constexpr double s
Definition Units.h:95
double UnitFromString(string u)
Definition UnitUtils.cxx:18
THE MAIN GENIE PROJECT NAMESPACE
Definition AlgCmp.h:25
@ kIStStableFinalState
Definition GHepStatus.h:30
const int kPdgAntiNuMu
Definition PDGCodes.h:31
const int kPdgNuMu
Definition PDGCodes.h:30