All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Public Member Functions | Private Member Functions | Private Attributes | List of all members
MultiPartVertex Class Reference
Inheritance diagram for MultiPartVertex:

Public Member Functions

 MultiPartVertex (fhicl::ParameterSet const &p)
 
 ~MultiPartVertex ()
 
 MultiPartVertex (MultiPartVertex const &)=delete
 
 MultiPartVertex (MultiPartVertex &&)=delete
 
MultiPartVertexoperator= (MultiPartVertex const &)=delete
 
MultiPartVertexoperator= (MultiPartVertex &&)=delete
 
void produce (art::Event &e) override
 
void beginRun (art::Run &run) override
 
void GenPosition (double &x, double &y, double &z)
 
std::array< double, 3U > extractDirection () const
 
void GenMomentum (const PartGenParam &param, const double &mass, double &px, double &py, double &pz)
 
std::vector< size_t > GenParticles () const
 

Private Member Functions

void abort (const std::string msg) const
 

Private Attributes

CLHEP::HepRandomEngine & fFlatEngine
 
std::unique_ptr< CLHEP::RandFlat > fFlatRandom
 
std::unique_ptr< CLHEP::RandGauss > fNormalRandom
 
std::vector< PartGenParam_param_v
 
double _t0
 
double _t0_sigma
 
std::array< double, 2 > _xrange
 
std::array< double, 2 > _yrange
 
std::array< double, 2 > _zrange
 
std::vector< std::vector
< unsigned short > > 
_tpc_v
 
size_t _multi_min
 
size_t _multi_max
 
unsigned short _debug
 

Detailed Description

Definition at line 50 of file MultiPartVertex_module.cc.

Constructor & Destructor Documentation

MultiPartVertex::MultiPartVertex ( fhicl::ParameterSet const &  p)
explicit

Definition at line 116 of file MultiPartVertex_module.cc.

117 : EDProducer(p)
118 , fFlatEngine(art::ServiceHandle<rndm::NuRandomService>()->createEngine(*this, "HepJamesRandom", "GenVertex"))
119  //, fFlatEngine(art::ServiceHandle<rndm::NuRandomService>()->createEngine(*this, "HepJamesRandom", "Gen", p, "Seed"))
120 // Initialize member data here.
121 {
122 
123  //
124  // Random engine initialization
125  //
126  fFlatRandom = std::make_unique<CLHEP::RandFlat>(fFlatEngine,0,1);
127  fNormalRandom = std::make_unique<CLHEP::RandGauss>(fFlatEngine);
128 
129  produces< std::vector<simb::MCTruth> >();
131 
132  _debug = p.get<unsigned short>("DebugMode",0);
133 
134  _t0 = p.get<double>("G4Time");
135  _t0_sigma = p.get<double>("G4TimeJitter");
136  if(_t0_sigma < 0) this->abort("Cannot have a negative value for G4 time jitter");
137 
138  _multi_min = p.get<size_t>("MultiMin");
139  _multi_max = p.get<size_t>("MultiMax");
140 
141  _tpc_v = p.get<std::vector<std::vector<unsigned short> > >("TPCRange");
142  auto const xrange = p.get<std::vector<double> > ("XRange");
143  auto const yrange = p.get<std::vector<double> > ("YRange");
144  auto const zrange = p.get<std::vector<double> > ("ZRange");
145 
146  auto const part_cfg = p.get<fhicl::ParameterSet>("ParticleParameter");
147 
148  _param_v.clear();
149  auto const pdg_v = part_cfg.get<std::vector<std::vector<int> > > ("PDGCode");
150  auto const minmult_v = part_cfg.get<std::vector<unsigned short> > ("MinMulti");
151  auto const maxmult_v = part_cfg.get<std::vector<unsigned short> > ("MaxMulti");
152  auto const weight_v = part_cfg.get<std::vector<double> > ("ProbWeight");
153 
154  auto kerange_v = part_cfg.get<std::vector<std::vector<double> > > ("KERange");
155  auto momrange_v = part_cfg.get<std::vector<std::vector<double> > > ("MomRange");
156 
157  if( (kerange_v.empty() && momrange_v.empty()) ||
158  (!kerange_v.empty() && !momrange_v.empty()) ) {
159  this->abort("Only one of KERange or MomRange must be empty!");
160  }
161 
162  bool use_mom = false;
163  if(kerange_v.empty()){
164  kerange_v = momrange_v;
165  use_mom = true;
166  }
167  // sanity check
168  if( pdg_v.size() != kerange_v.size() ||
169  pdg_v.size() != minmult_v.size() ||
170  pdg_v.size() != maxmult_v.size() ||
171  pdg_v.size() != weight_v.size() )
172  this->abort("configuration parameters have incompatible lengths!");
173 
174  // further sanity check (1 more depth for some double-array)
175  for(auto const& r : pdg_v ) { if( r.empty() ) this->abort("PDG code not given!"); }
176  for(auto const& r : kerange_v) { if( r.size()!=2) this->abort("Incompatible legnth @ KE vector!"); }
177 
178  size_t multi_min = 0;
179  for(size_t idx=0; idx<minmult_v.size(); ++idx) {
180  if(minmult_v[idx] > maxmult_v[idx]) this->abort("Particle MinMulti > Particle MaxMulti!");
181  if(minmult_v[idx] > _multi_max) this->abort("Particle MinMulti > overall MultiMax!");
182  multi_min += minmult_v[idx];
183  }
184  _multi_min = std::max(_multi_min, multi_min);
185  if(_multi_max < _multi_min) this->abort("Overall MultiMax <= overall MultiMin!");
186 
187  /*
188  if(!xrange.empty() && xrange.size() >2) this->abort("Incompatible legnth @ X vector!" );
189  if(!yrange.empty() && yrange.size() >2) this->abort("Incompatible legnth @ Y vector!" );
190  if(!zrange.empty() && zrange.size() >2) this->abort("Incompatible legnth @ Z vector!" );
191 
192  // range register
193  if(xrange.size()==1) { _xrange[0] = _xrange[1] = xrange[0]; }
194  if(xrange.size()==2) { _xrange[0] = xrange[0]; _xrange[1] = xrange[1]; }
195  if(yrange.size()==1) { _yrange[0] = _yrange[1] = yrange[0]; }
196  if(yrange.size()==2) { _yrange[0] = yrange[0]; _yrange[1] = yrange[1]; }
197  if(zrange.size()==1) { _zrange[0] = _zrange[1] = zrange[0]; }
198  if(zrange.size()==2) { _zrange[0] = zrange[0]; _zrange[1] = zrange[1]; }
199  */
200 
201  if(!xrange.empty() && xrange.size() >2) this->abort("Incompatible legnth @ X vector!" );
202  if(!yrange.empty() && yrange.size() >2) this->abort("Incompatible legnth @ Y vector!" );
203  if(!zrange.empty() && zrange.size() >2) this->abort("Incompatible legnth @ Z vector!" );
204 
205  // slight modification from mpv: define the overall volume across specified TPC IDs + range options
206  double xmin,xmax,ymin,ymax,zmin,zmax;
207  xmin = ymin = zmin = 1.e20;
208  xmax = ymax = zmax = -1.e20;
209  // Implementation of required member function here.
210  auto geop = lar::providerFrom<geo::Geometry>();
211  for(auto const& tpc_id : _tpc_v) {
212  assert(tpc_id.size() == 2);
213  size_t cid = tpc_id[0];
214  size_t tid = tpc_id[1];
215  auto const& cryostat = geop->Cryostat(cid);
216  assert(cryostat.HasTPC(tid));
217 
218  auto const& tpc = cryostat.TPC(tid);
219  auto const& tpcabox = tpc.ActiveBoundingBox();
220  xmin = std::min(tpcabox.MinX(), xmin);
221  ymin = std::min(tpcabox.MinY(), ymin);
222  zmin = std::min(tpcabox.MinZ(), zmin);
223  xmax = std::max(tpcabox.MaxX(), xmax);
224  ymax = std::max(tpcabox.MaxY(), ymax);
225  zmax = std::max(tpcabox.MaxZ(), zmax);
226 
227  if(_debug) {
228  std::cout << "Using Cryostat " << tpc_id[0] << " TPC " << tpc_id[1]
229  << " ... X " << xmin << " => " << xmax
230  << " ... Y " << ymin << " => " << ymax
231  << " ... Z " << zmin << " => " << zmax
232  << std::endl;
233  }
234  }
235 
236  // range register
237  if(xrange.size()==1) { _xrange[0] = _xrange[1] = xrange[0]; }
238  if(yrange.size()==1) { _yrange[0] = _yrange[1] = yrange[0]; }
239  if(zrange.size()==1) { _zrange[0] = _zrange[1] = zrange[0]; }
240  if(xrange.size()==2) { _xrange[0] = xrange[0]; _xrange[1] = xrange[1]; }
241  if(yrange.size()==2) { _yrange[0] = yrange[0]; _yrange[1] = yrange[1]; }
242  if(zrange.size()==2) { _zrange[0] = zrange[0]; _zrange[1] = zrange[1]; }
243 
244  _xrange[0] = xmin + _xrange[0];
245  _xrange[1] = xmax - _xrange[1];
246  _yrange[0] = ymin + _yrange[0];
247  _yrange[1] = ymax - _yrange[1];
248  _zrange[0] = zmin + _zrange[0];
249  _zrange[1] = zmax - _zrange[1];
250 
251  // check
252  assert(_xrange[0] <= _xrange[1]);
253  assert(_yrange[0] <= _yrange[1]);
254  assert(_zrange[0] <= _zrange[1]);
255 
256  if(_debug>0) {
257  std::cout<<"Particle generation world boundaries..."<<std::endl
258  <<"X " << _xrange[0] << " => " << _xrange[1] << std::endl
259  <<"Y " << _yrange[0] << " => " << _yrange[1] << std::endl
260  <<"Z " << _zrange[0] << " => " << _zrange[1] << std::endl;
261  }
262 
263 
264  // register
265  //auto db = new TDatabasePDG;
266  auto db = TDatabasePDG::Instance();
267  for(size_t idx=0; idx<pdg_v.size(); ++idx) {
268  auto const& pdg = pdg_v[idx];
269  auto const& kerange = kerange_v[idx];
270  PartGenParam param;
271  param.use_mom = use_mom;
272  param.pdg = pdg;
273  param.kerange[0] = kerange[0];
274  param.kerange[1] = kerange[1];
275  param.mass.resize(pdg.size());
276  param.multi[0] = minmult_v[idx];
277  param.multi[1] = maxmult_v[idx];
278  param.weight = weight_v[idx];
279  for(size_t i=0; i<pdg.size(); ++i)
280  param.mass[i] = db->GetParticle(param.pdg[i])->Mass();
281 
282  // sanity check
283  if(kerange[0]<0 || kerange[1]<0)
284  this->abort("You provided negative energy? Fuck off Mr. Trump.");
285 
286  // overall range check
287  if(param.kerange[0] > param.kerange[1]) this->abort("KE range has no phase space...");
288 
289  if(_debug>0) {
290  std::cout << "Generating particle (PDG";
291  for(auto const& pdg : param.pdg) std::cout << " " << pdg;
292  std::cout << ")" << std::endl
293  << (param.use_mom ? " KE range ....... " : " Mom range ....... ")
294  << param.kerange[0] << " => " << param.kerange[1] << " MeV" << std::endl
295  << std::endl;
296  }
297 
298  _param_v.push_back(param);
299  }
300 }
std::vector< std::vector< unsigned short > > _tpc_v
var pdg
Definition: selectors.fcl:14
CLHEP::HepRandomEngine & fFlatEngine
std::vector< int > pdg
pdgs p
Definition: selectors.fcl:22
produces< sumdata::RunData, art::InRun >()
std::unique_ptr< CLHEP::RandFlat > fFlatRandom
std::array< double, 2 > _xrange
std::vector< PartGenParam > _param_v
process_name pandoraGausCryo1 vertexChargeCryo1 vertexStubCryo1 xmin
std::array< double, 2 > _zrange
std::vector< double > mass
std::array< double, 2 > kerange
void abort(const std::string msg) const
height to which particles are projected pnfs larsoft persistent physics cosmics Fermilab CORSIKA standard He_showers_ * db
esac echo uname r
std::unique_ptr< CLHEP::RandGauss > fNormalRandom
std::array< size_t, 2 > multi
BEGIN_PROLOG could also be cout
std::array< double, 2 > _yrange
MultiPartVertex::~MultiPartVertex ( )

Definition at line 113 of file MultiPartVertex_module.cc.

114 { }
MultiPartVertex::MultiPartVertex ( MultiPartVertex const &  )
delete
MultiPartVertex::MultiPartVertex ( MultiPartVertex &&  )
delete

Member Function Documentation

void MultiPartVertex::abort ( const std::string  msg) const
private

Definition at line 107 of file MultiPartVertex_module.cc.

108 {
109  std::cerr << "\033[93m" << msg.c_str() << "\033[00m" << std::endl;
110  throw std::exception();
111 }
BEGIN_PROLOG could also be cerr
void MultiPartVertex::beginRun ( art::Run &  run)
override

Definition at line 302 of file MultiPartVertex_module.cc.

303 {
304  // grab the geometry object to see what geometry we are using
305  art::ServiceHandle<geo::Geometry> geo;
306 
307  std::unique_ptr<sumdata::RunData> runData(new sumdata::RunData(geo->DetectorName()));
308 
309  run.put(std::move(runData));
310 
311  return;
312 }
std::array< double, 3U > MultiPartVertex::extractDirection ( ) const

Definition at line 404 of file MultiPartVertex_module.cc.

404  {
405  double px, py, pz;
406  px = fNormalRandom->fire(0, 1);
407  py = fNormalRandom->fire(0, 1);
408  pz = fNormalRandom->fire(0, 1);
409  double p = std::hypot(px, py, pz);
410  px = px / p;
411  py = py / p;
412  pz = pz / p;
413  std::array<double, 3U> result = { px, py, pz };
414  return result;
415 }
BEGIN_PROLOG pz
Definition: filemuons.fcl:10
pdgs p
Definition: selectors.fcl:22
BEGIN_PROLOG px
Definition: filemuons.fcl:10
process_name physics producers generator physics producers generator physics producers generator py
std::unique_ptr< CLHEP::RandGauss > fNormalRandom
void MultiPartVertex::GenMomentum ( const PartGenParam param,
const double &  mass,
double &  px,
double &  py,
double &  pz 
)

Definition at line 417 of file MultiPartVertex_module.cc.

417  {
418 
419  double tot_energy = 0;
420  if(param.use_mom)
421  tot_energy = sqrt(cet::square(fFlatRandom->fire(param.kerange[0],param.kerange[1])) + cet::square(mass));
422  else
423  tot_energy = fFlatRandom->fire(param.kerange[0],param.kerange[1]) + mass;
424 
425  double mom_mag = sqrt(cet::square(tot_energy) - cet::square(mass));
426 
427  /* Generating unit vector with uniform distribution
428  * in direction = over the sphere.
429  *
430  * It is sufficient to draw a normal variable in
431  * each direction and normalize.
432  *
433  * https://mathworld.wolfram.com/SpherePointPicking.html
434  */
435 
436  std::array<double, 3U> p = extractDirection();
437  px = p[0]; py = p[1]; pz = p[2];
438 
439  if(_debug>1)
440  std::cout << " Direction : (" << px << "," << py << "," << pz << ")" << std::endl
441  << " Momentum : " << mom_mag << " [MeV/c]" << std::endl
442  << " Energy : " << tot_energy << " [MeV/c^2]" << std::endl;
443  px *= mom_mag;
444  py *= mom_mag;
445  pz *= mom_mag;
446 
447 }
BEGIN_PROLOG pz
Definition: filemuons.fcl:10
pdgs p
Definition: selectors.fcl:22
std::unique_ptr< CLHEP::RandFlat > fFlatRandom
std::array< double, 3U > extractDirection() const
BEGIN_PROLOG px
Definition: filemuons.fcl:10
process_name physics producers generator physics producers generator physics producers generator py
float mass
Definition: dedx.py:47
std::array< double, 2 > kerange
BEGIN_PROLOG could also be cout
std::vector< size_t > MultiPartVertex::GenParticles ( ) const

Definition at line 314 of file MultiPartVertex_module.cc.

314  {
315 
316  std::vector<size_t> result;
317  std::vector<size_t> gen_count_v(_param_v.size(),0);
318 
319  int num_part = (int)(fFlatRandom->fire(_multi_min,_multi_max+1-1.e-10));
320 
321  // generate min multiplicity first
322  std::vector<double> weight_v(_param_v.size(),0);
323  for(size_t idx=0; idx<_param_v.size(); ++idx) {
324  weight_v[idx] = _param_v[idx].weight;
325  for(size_t ctr=0; ctr<_param_v[idx].multi[0]; ++ctr) {
326  result.push_back(idx);
327  gen_count_v[idx] += 1;
328  num_part -= 1;
329  }
330  if(gen_count_v[idx] >= _param_v[idx].multi[1])
331  weight_v[idx] = 0.;
332  }
333 
334  assert(num_part >= 0);
335 
336  while(num_part) {
337 
338  double total_weight = 0;
339  for(auto const& v : weight_v) total_weight += v;
340 
341  double rval = 0;
342  rval = fFlatRandom->fire(0,total_weight);
343 
344  size_t idx = 0;
345  for(idx = 0; idx < weight_v.size(); ++idx) {
346  rval -= weight_v[idx];
347  if(rval <=0.) break;
348  }
349 
350  // register to the output
351  result.push_back(idx);
352 
353  // if generation count exceeds max, set probability weight to be 0
354  gen_count_v[idx] += 1;
355  if(gen_count_v[idx] >= _param_v[idx].multi[1])
356  weight_v[idx] = 0.;
357 
358  --num_part;
359  }
360  return result;
361 }
std::unique_ptr< CLHEP::RandFlat > fFlatRandom
std::vector< PartGenParam > _param_v
void MultiPartVertex::GenPosition ( double &  x,
double &  y,
double &  z 
)

Definition at line 364 of file MultiPartVertex_module.cc.

364  {
365 
366  x = fFlatRandom->fire(_xrange[0],_xrange[1]);
367  y = fFlatRandom->fire(_yrange[0],_yrange[1]);
368  z = fFlatRandom->fire(_zrange[0],_zrange[1]);
369 
370  if(_debug>0) {
371  std::cout << "Generating a rain particle at ("
372  << x << "," << y << "," << z << ")" << std::endl;
373  }
374 }
process_name opflash particleana ie ie ie z
process_name opflash particleana ie x
std::unique_ptr< CLHEP::RandFlat > fFlatRandom
std::array< double, 2 > _xrange
process_name opflash particleana ie ie y
std::array< double, 2 > _zrange
BEGIN_PROLOG could also be cout
std::array< double, 2 > _yrange
MultiPartVertex& MultiPartVertex::operator= ( MultiPartVertex const &  )
delete
MultiPartVertex& MultiPartVertex::operator= ( MultiPartVertex &&  )
delete
void MultiPartVertex::produce ( art::Event &  e)
override

Definition at line 449 of file MultiPartVertex_module.cc.

450 {
451  if(_debug>0) std::cout << "Processing a new event..." << std::endl;
452 
453  std::unique_ptr< std::vector<simb::MCTruth> > mctArray(new std::vector<simb::MCTruth>);
454 
455  double g4_time = fFlatRandom->fire(_t0 - _t0_sigma/2., _t0 + _t0_sigma/2.);
456 
457  double x, y, z;
458  GenPosition(x,y,z);
459  TLorentzVector pos(x,y,z,g4_time);
460 
461  simb::MCTruth mct;
462 
463  mct.SetOrigin(simb::kBeamNeutrino);
464 
465  std::vector<simb::MCParticle> part_v;
466 
467  auto const param_idx_v = GenParticles();
468  if(_debug)
469  std::cout << "Event Vertex @ (" << x << "," << y << "," << z << ") ... " << param_idx_v.size() << " particles..." << std::endl;
470 
471  for(size_t idx=0; idx<param_idx_v.size(); ++idx) {
472  auto const& param = _param_v[param_idx_v[idx]];
473  double px,py,pz;
474  // decide which particle
475  size_t pdg_index = (size_t)(fFlatRandom->fire(0,param.pdg.size()-1.e-10));
476  auto const& pdg = param.pdg[pdg_index];
477  auto const& mass = param.mass[pdg_index];
478  if(_debug) std::cout << " " << idx << "th instance PDG " << pdg << std::endl;
479  GenMomentum(param,mass,px,py,pz);
480  TLorentzVector mom(px,py,pz,sqrt(cet::square(px)+cet::square(py)+cet::square(pz)+cet::square(mass)));
481  //simb::MCParticle part(mct.NParticles(), pdg, "primary", 0, mass, 1);
482  simb::MCParticle part(part_v.size(), pdg, "primary", 0, mass, 1);
483  part.AddTrajectoryPoint(pos,mom);
484  part_v.emplace_back(std::move(part));
485  }
486 
487  if(_debug) std::cout << "Total number particles: " << mct.NParticles() << std::endl;
488 
489  simb::MCParticle nu(mct.NParticles(), 16, "primary", mct.NParticles(), 0, 0);
490  double px=0;
491  double py=0;
492  double pz=0;
493  double en=0;
494  for(auto const& part : part_v) {
495  px += part.Momentum().Px();
496  py += part.Momentum().Py();
497  pz += part.Momentum().Pz();
498  en += part.Momentum().E();
499  }
500  TLorentzVector mom(px,py,pz,en);
501  nu.AddTrajectoryPoint(pos,mom);
502 
503  mct.Add(nu);
504  for(auto& part : part_v)
505  mct.Add(part);
506 
507  // Set the neutrino for the MCTruth object:
508  // NOTE: currently these parameters are all pretty much a guess...
509  mct.SetNeutrino(simb::kCC,
510  simb::kQE, // not sure what the mode should be here, assumed that these are all QE???
511  simb::kCCQE, // not sure what the int_type should be either...
512  0, // target is AR40? not sure how to specify that...
513  0, // nucleon pdg ???
514  0, // quark pdg ???
515  -1.0, // W ??? - not sure how to calculate this from the above
516  -1.0, // X ??? - not sure how to calculate this from the above
517  -1.0, // Y ??? - not sure how to calculate this from the above
518  -1.0); // Qsqr ??? - not sure how to calculate this from the above
519 
520  mctArray->push_back(mct);
521 
522  e.put(std::move(mctArray));
523 }
process_name opflash particleana ie ie ie z
var pdg
Definition: selectors.fcl:14
process_name opflash particleana ie x
BEGIN_PROLOG pz
Definition: filemuons.fcl:10
std::unique_ptr< CLHEP::RandFlat > fFlatRandom
std::vector< size_t > GenParticles() const
std::vector< PartGenParam > _param_v
void GenMomentum(const PartGenParam &param, const double &mass, double &px, double &py, double &pz)
Charged-current interactions.
Definition: IPrediction.h:38
process_name opflash particleana ie ie y
void GenPosition(double &x, double &y, double &z)
BEGIN_PROLOG px
Definition: filemuons.fcl:10
process_name physics producers generator physics producers generator physics producers generator py
float mass
Definition: dedx.py:47
do i e
charged current quasi-elastic
Definition: SREnums.h:86
BEGIN_PROLOG SN nu
BEGIN_PROLOG could also be cout

Member Data Documentation

unsigned short MultiPartVertex::_debug
private

Definition at line 104 of file MultiPartVertex_module.cc.

size_t MultiPartVertex::_multi_max
private

Definition at line 101 of file MultiPartVertex_module.cc.

size_t MultiPartVertex::_multi_min
private

Definition at line 100 of file MultiPartVertex_module.cc.

std::vector<PartGenParam> MultiPartVertex::_param_v
private

Definition at line 85 of file MultiPartVertex_module.cc.

double MultiPartVertex::_t0
private

Definition at line 88 of file MultiPartVertex_module.cc.

double MultiPartVertex::_t0_sigma
private

Definition at line 89 of file MultiPartVertex_module.cc.

std::vector<std::vector<unsigned short> > MultiPartVertex::_tpc_v
private

Definition at line 97 of file MultiPartVertex_module.cc.

std::array<double,2> MultiPartVertex::_xrange
private

Definition at line 92 of file MultiPartVertex_module.cc.

std::array<double,2> MultiPartVertex::_yrange
private

Definition at line 93 of file MultiPartVertex_module.cc.

std::array<double,2> MultiPartVertex::_zrange
private

Definition at line 94 of file MultiPartVertex_module.cc.

CLHEP::HepRandomEngine& MultiPartVertex::fFlatEngine
private

Definition at line 77 of file MultiPartVertex_module.cc.

std::unique_ptr<CLHEP::RandFlat> MultiPartVertex::fFlatRandom
private

Definition at line 78 of file MultiPartVertex_module.cc.

std::unique_ptr<CLHEP::RandGauss> MultiPartVertex::fNormalRandom
private

Definition at line 79 of file MultiPartVertex_module.cc.


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