DetectorPropertiesStandard.cxx
Go to the documentation of this file.
1 /**
2  * @file lardataalg/DetectorInfo/DetectorPropertiesStandard.cxx
3  * @brief Separation of service from Detector info class.
4  * @author Jonathan Paley (jpaley@fnal.gov)
5  */
6 
7 // Framework includes
8 
9 // LArSoft includes
11 #include "larcorealg/CoreUtils/ProviderUtil.h" // lar::IgnorableProviderConfigKeys()
17 
18 #include "cetlib/pow.h"
20 
21 // Art includes
22 #include "fhiclcpp/types/Table.h"
23 
24 // C/C++ libraries
25 #include <sstream> // std::ostringstream
26 
27 namespace detinfo {
28 
29  //--------------------------------------------------------------------
31  const geo::GeometryCore* geo,
32  const detinfo::LArProperties* lp,
33  std::set<std::string> const& ignore_params)
34  : fLP(lp), fGeo(geo)
35  {
36  ValidateAndConfigure(pset, ignore_params);
37  }
38 
39  //--------------------------------------------------------------------
40  void
42  std::set<std::string> const& ignore_params)
43  {
44  {
45  mf::LogInfo debug("setupProvider<DetectorPropertiesStandard>");
46 
47  debug << "Asked to ignore " << ignore_params.size() << " keys:";
48  for (auto const& key : ignore_params)
49  debug << " '" << key << "'";
50  }
51 
52  std::set<std::string> ignorable_keys = lar::IgnorableProviderConfigKeys();
53  ignorable_keys.insert(ignore_params.begin(), ignore_params.end());
54 
55  // parses and validates the parameter set:
56  fhicl::Table<Configuration_t> const config{p, ignorable_keys};
57 
58  fEfield = config().Efield();
59  fElectronlifetime = config().Electronlifetime();
60  fTemperature = config().Temperature();
61  fElectronsToADC = config().ElectronsToADC();
62  fNumberTimeSamples = config().NumberTimeSamples();
63  fReadOutWindowSize = config().ReadOutWindowSize();
64 
65  std::set<geo::View_t> present_views;
66  if (config().TimeOffsetU(fTimeOffsetU)) present_views.insert(geo::kU);
67  if (config().TimeOffsetV(fTimeOffsetV)) present_views.insert(geo::kV);
68  if (config().TimeOffsetZ(fTimeOffsetZ)) present_views.insert(geo::kZ);
69  if (config().TimeOffsetY(fTimeOffsetY)) present_views.insert(geo::kY);
70  if (config().TimeOffsetX(fTimeOffsetX)) present_views.insert(geo::kX);
71 
72  std::string const errors = CheckTimeOffsets(present_views);
73  if (!errors.empty()) {
74  throw cet::exception("DetectorPropertiesStandard") << "Detected configuration errors: \n"
75  << errors;
76  }
77 
78  fSternheimerParameters.a = config().SternheimerA();
79  fSternheimerParameters.k = config().SternheimerK();
80  fSternheimerParameters.x0 = config().SternheimerX0();
81  fSternheimerParameters.x1 = config().SternheimerX1();
82  fSternheimerParameters.cbar = config().SternheimerCbar();
83 
84  fDriftVelFudgeFactor = config().DriftVelFudgeFactor();
85 
86  fUseIcarusMicrobooneDriftModel = config().UseIcarusMicrobooneDriftModel();
87 
88  fIncludeInterPlanePitchInXTickOffsets = config().IncludeInterPlanePitchInXTickOffsets();
89 
90  fSimpleBoundary = config().SimpleBoundary();
91  }
92 
93  //------------------------------------------------------------------------------------//
94  double
95  DetectorPropertiesStandard::Efield(unsigned int const planegap) const
96  {
97  if (planegap >= fEfield.size())
98  throw cet::exception("DetectorPropertiesStandard")
99  << "requesting Electric field in a plane gap that is not defined\n";
100 
101  return fEfield[planegap];
102  }
103 
104  //------------------------------------------------
105  double
106  DetectorPropertiesStandard::Density(double temperature) const
107  {
108  // Default temperature use internal value.
109  if (temperature == 0.) temperature = Temperature();
110 
111  return -0.00615 * temperature + 1.928;
112  }
113 
114  //----------------------------------------------------------------------------------
115  // Restricted mean energy loss (dE/dx) in units of MeV/cm.
116  //
117  // For unrestricted mean energy loss, set tcut = 0, or tcut large.
118  //
119  // Arguments:
120  //
121  // mom - Momentum of incident particle in GeV/c.
122  // mass - Mass of incident particle in GeV/c^2.
123  // tcut - Maximum kinetic energy of delta rays (MeV).
124  //
125  // Returned value is positive.
126  //
127  // Based on Bethe-Bloch formula as contained in particle data book.
128  // Material parameters (stored in larproperties.fcl) are taken from
129  // pdg web site http://pdg.lbl.gov/AtomicNuclearProperties/
130  //
131  double
132  DetectorPropertiesStandard::Eloss(double mom, double mass, double tcut) const
133  {
134  // Some constants.
135  constexpr double K = 0.307075; // 4 pi N_A r_e^2 m_e c^2 (MeV cm^2/mol).
136  constexpr double me = 0.510998918; // Electron mass (MeV/c^2).
137 
138  // Calculate kinematic quantities.
139  double const bg = mom / mass; // beta*gamma.
140  double const gamma = sqrt(1. + bg * bg); // gamma.
141  double const beta = bg / gamma; // beta (velocity).
142  double const mer = 0.001 * me / mass; // electron mass / mass of incident particle.
143  double const tmax =
144  2. * me * bg * bg / (1. + 2. * gamma * mer + mer * mer); // Maximum delta ray energy (MeV).
145 
146  // Make sure tcut does not exceed tmax.
147  if (tcut == 0. || tcut > tmax) tcut = tmax;
148 
149  // Calculate density effect correction (delta).
150  double const x = std::log10(bg);
151  double delta = 0.;
152  if (x >= fSternheimerParameters.x0) {
153  delta = 2. * std::log(10.) * x - fSternheimerParameters.cbar;
154  if (x < fSternheimerParameters.x1)
155  delta += fSternheimerParameters.a *
157  }
158 
159  // Calculate stopping number.
160  double B =
161  0.5 * std::log(2. * me * bg * bg * tcut / (1.e-12 * cet::square(fLP->ExcitationEnergy()))) -
162  0.5 * beta * beta * (1. + tcut / tmax) - 0.5 * delta;
163 
164  // Don't let the stopping number become negative.
165  if (B < 1.) B = 1.;
166 
167  // Calculate dE/dx.
168  return Density() * K * fLP->AtomicNumber() * B / (fLP->AtomicMass() * beta * beta);
169  }
170 
171  //----------------------------------------------------------------------------------
172  double
173  DetectorPropertiesStandard::ElossVar(double const mom, double const mass) const
174  {
175  // Some constants.
176  constexpr double K = 0.307075; // 4 pi N_A r_e^2 m_e c^2 (MeV cm^2/mol).
177  constexpr double me = 0.510998918; // Electron mass (MeV/c^2).
178 
179  // Calculate kinematic quantities.
180  double const bg = mom / mass; // beta*gamma.
181  double const gamma2 = 1. + bg * bg; // gamma^2.
182  double const beta2 = bg * bg / gamma2; // beta^2.
183  return gamma2 * (1. - 0.5 * beta2) * me * (fLP->AtomicNumber() / fLP->AtomicMass()) * K *
184  Density();
185  }
186 
187  //------------------------------------------------------------------------------------//
188  double
189  DetectorPropertiesStandard::DriftVelocity(double efield, double temperature) const
190  {
191  // Drift Velocity as a function of Electric Field and LAr Temperature
192  // from : W. Walkowiak, NIM A 449 (2000) 288-294
193  //
194  // Option to use MicroBooNE+ICARUS model (as in arXiv:2008.09765) provided as
195  // well, with temperature depenence as prescribed by Mike Mooney based on
196  // looking at the Walkowiak data.
197  //
198  // Efield should have units of kV/cm
199  // Temperature should have units of Kelvin
200 
201  // Default Efield, use internal value.
202  if (efield == 0.) efield = Efield();
203 
204  if (efield > 4.0)
205  mf::LogWarning("DetectorPropertiesStandard")
206  << "DriftVelocity Warning! : E-field value of " << efield
207  << " kV/cm is outside of range covered by drift"
208  << " velocity parameterization. Returned value"
209  << " may not be correct";
210 
211  // Default temperature use internal value.
212  if (temperature == 0.) temperature = Temperature();
213 
214  if (temperature < 87.0 || temperature > 94.0)
215  mf::LogWarning("DetectorPropertiesStandard")
216  << "DriftVelocity Warning! : Temperature value of " << temperature
217  << " K is outside of range covered by drift velocity"
218  << " parameterization. Returned value may not be"
219  << " correct";
220 
221  double vd;
222 
224  double const tshift = -87.203 + temperature;
225  double const xFit = 0.0938163 - 0.0052563 * tshift - 0.0001470 * tshift * tshift;
226  double const uFit = 5.18406 + 0.01448 * tshift - 0.003497 * tshift * tshift -
227  0.000516 * tshift * tshift * tshift;
228 
229  // Icarus Parameter Set, use as default
230  constexpr double P1 = -0.04640; // K^-1
231  constexpr double P2 = 0.01712; // K^-1
232  constexpr double P3 = 1.88125; // (kV/cm)^-1
233  constexpr double P4 = 0.99408; // kV/cm
234  constexpr double P5 = 0.01172; // (kV/cm)^-P6
235  constexpr double P6 = 4.20214;
236  constexpr double T0 = 105.749; // K
237 
238  // Walkowiak Parameter Set
239  constexpr double P1W = -0.01481; // K^-1
240  constexpr double P2W = -0.0075; // K^-1
241  constexpr double P3W = 0.141; // (kV/cm)^-1
242  constexpr double P4W = 12.4; // kV/cm
243  constexpr double P5W = 1.627; // (kV/cm)^-P6
244  constexpr double P6W = 0.317;
245  constexpr double T0W = 90.371; // K
246 
247  // From Craig Thorne . . . currently not documented
248  // smooth transition from linear at small fields to
249  // icarus fit at most fields to Walkowiak at very high fields
250  if (efield < xFit)
251  vd = efield * uFit;
252  else if (efield < 0.619) {
253  vd = ((P1 * (temperature - T0) + 1) *
254  (P3 * efield * std::log(1 + P4 / efield) + P5 * std::pow(efield, P6)) +
255  P2 * (temperature - T0));
256  }
257  else if (efield < 0.699) {
258  vd = 12.5 * (efield - 0.619) *
259  ((P1W * (temperature - T0W) + 1) *
260  (P3W * efield * std::log(1 + P4W / efield) + P5W * std::pow(efield, P6W)) +
261  P2W * (temperature - T0W)) +
262  12.5 * (0.699 - efield) *
263  ((P1 * (temperature - T0) + 1) *
264  (P3 * efield * std::log(1 + P4 / efield) + P5 * std::pow(efield, P6)) +
265  P2 * (temperature - T0));
266  }
267  else {
268  vd = ((P1W * (temperature - T0W) + 1) *
269  (P3W * efield * std::log(1 + P4W / efield) + P5W * std::pow(efield, P6W)) +
270  P2W * (temperature - T0W));
271  }
272  }
273 
274  // MicroBooNE+ICARUS model (arXiv:2008.09765) with temperature dependence given by
275  // Mike Mooney based on looking at Walkowiak data (NIM A 449 (2000) 288-294)
277  constexpr double P0 = 0.;
278  constexpr double P1 = 5.53416;
279  constexpr double P2 = -6.53093;
280  constexpr double P3 = 3.20752;
281  constexpr double P4 = 0.389696;
282  constexpr double P5 = -0.556184;
283  vd = (1.0 - 0.0184 * (temperature - 89.0)) *
284  (P0 + P1 * cet::pow<1>(efield) + P2 * cet::pow<2>(efield) + P3 * cet::pow<3>(efield) +
285  P4 * cet::pow<4>(efield) + P5 * cet::pow<5>(efield));
286  }
287 
288  vd *= fDriftVelFudgeFactor / 10.;
289 
290  return vd; // in cm/us
291  }
292 
293  //----------------------------------------------------------------------------------
294  // The below function assumes that the user has applied the lifetime
295  // correction and effective pitch between the wires (usually after 3D
296  // reconstruction). Using with mean wire pitch will not give correct results.
297  // parameters:
298  // dQdX in electrons/cm, charge (amplitude or integral obtained) divided by
299  // effective pitch for a given 3D track.
300  // Electric Field in the drift region in KV/cm/
301  // returns dEdX in MeV/cm
302  double
304  {
305  return BirksCorrection(dQdx, Efield());
306  }
307  double
308  DetectorPropertiesStandard::BirksCorrection(double dQdx, double E_field) const
309  {
310  // Correction for charge quenching using parameterization from
311  // S.Amoruso et al., NIM A 523 (2004) 275
312 
313  constexpr double A3t = util::kRecombA;
314  double K3t = util::kRecombk; // in KV/cm*(g/cm^2)/MeV
315  double const rho = Density(); // LAr density in g/cm^3
316  constexpr double Wion = 1000. / util::kGeVToElectrons; // 23.6 eV = 1e, Wion in MeV/e
317  K3t /= rho; // KV/MeV
318  double const dEdx = dQdx / (A3t / Wion - K3t / E_field * dQdx); // MeV/cm
319 
320  return dEdx;
321  }
322 
323  //----------------------------------------------------------------------------------
324  // Modified Box model correction
325  double
327  {
328  return ModBoxCorrection(dQdx, Efield());
329  }
330  double
331  DetectorPropertiesStandard::ModBoxCorrection(double dQdx, double E_field) const
332  {
333  // Modified Box model correction has better behavior than the Birks
334  // correction at high values of dQ/dx.
335  double const rho = Density(); // LAr density in g/cm^3
336  constexpr double Wion = 1000. / util::kGeVToElectrons; // 23.6 eV = 1e, Wion in MeV/e
337  double const Beta = util::kModBoxB / (rho * E_field);
338  constexpr double Alpha = util::kModBoxA;
339  double const dEdx = (exp(Beta * Wion * dQdx) - Alpha) / Beta;
340 
341  return dEdx;
342  }
343 
344  //--------------------------------------------------------------------
345  // x<--> ticks conversion methods
346  //
347  // Ben Jones April 2012,
348  // based on code by Herb Greenlee in SpacePointService
349  //
350 
351  //--------------------------------------------------------------------
352  // Recalculate x<-->ticks conversion parameters from detector constants
353 
356  {
357  double const samplingRate = sampling_rate(clock_data);
358  double const efield = Efield();
359  double const temperature = Temperature();
360  double const driftVelocity = DriftVelocity(efield, temperature);
361  double const x_ticks_coefficient = 0.001 * driftVelocity * samplingRate;
362 
363  double const triggerOffset = trigger_offset(clock_data);
364 
365  std::vector<std::vector<std::vector<double>>> x_ticks_offsets(fGeo->Ncryostats());
366  std::vector<std::vector<double>> drift_direction(fGeo->Ncryostats());
367 
368  for (size_t cstat = 0; cstat < fGeo->Ncryostats(); ++cstat) {
369  x_ticks_offsets[cstat].resize(fGeo->Cryostat(cstat).NTPC());
370  drift_direction[cstat].resize(fGeo->Cryostat(cstat).NTPC());
371 
372  for (size_t tpc = 0; tpc < fGeo->Cryostat(cstat).NTPC(); ++tpc) {
373  const geo::TPCGeo& tpcgeom = fGeo->Cryostat(cstat).TPC(tpc);
374 
375  const double dir((tpcgeom.DriftDirection() == geo::kNegX) ? +1.0 : -1.0);
376  drift_direction[cstat][tpc] = dir;
377 
378  int nplane = tpcgeom.Nplanes();
379  x_ticks_offsets[cstat][tpc].resize(nplane, 0.);
380  for (int plane = 0; plane < nplane; ++plane) {
381  const geo::PlaneGeo& pgeom = tpcgeom.Plane(plane);
382 
383  // Calculate geometric time offset.
384  // only works if xyz[0]<=0
385  const double* xyz = tpcgeom.PlaneLocation(0);
386 
387  x_ticks_offsets[cstat][tpc][plane] =
388  -xyz[0] / (dir * x_ticks_coefficient) + triggerOffset;
389 
391  // Get field in gap between planes
392  double efieldgap[3];
393  double driftVelocitygap[3];
394  double x_ticks_coefficient_gap[3];
395  for (int igap = 0; igap < 3; ++igap) {
396  efieldgap[igap] = Efield(igap);
397  driftVelocitygap[igap] = DriftVelocity(efieldgap[igap], temperature);
398  x_ticks_coefficient_gap[igap] = 0.001 * driftVelocitygap[igap] * samplingRate;
399  }
400 
401  if (nplane == 3) {
402  /*
403  | ---------- plane = 2 (collection)
404  | Coeff[2]
405  | ---------- plane = 1 (2nd induction)
406  | Coeff[1]
407  | ---------- plane = 0 (1st induction) x = xyz[0]
408  | Coeff[0]
409  | ---------- x = 0
410  V For plane = 0, t offset is -xyz[0]/Coeff[0]
411  x */
412  for (int ip = 0; ip < plane; ++ip) {
413  x_ticks_offsets[cstat][tpc][plane] +=
414  tpcgeom.PlanePitch(ip, ip + 1) / x_ticks_coefficient_gap[ip + 1];
415  }
416  }
417  else if (nplane == 2) { ///< special case for ArgoNeuT
418  /*
419  | ---------- plane = 1 (collection)
420  | Coeff[2]
421  | ---------- plane = 0 (2nd induction) x = xyz[0]
422  | ---------- x = 0, Coeff[1]
423  V ---------- first induction plane
424  x Coeff[0]
425  For plane = 0, t offset is pitch/Coeff[1] -
426  (pitch+xyz[0])/Coeff[0] = -xyz[0]/Coeff[0] -
427  pitch*(1/Coeff[0]-1/Coeff[1])
428  */
429  for (int ip = 0; ip < plane; ++ip) {
430  x_ticks_offsets[cstat][tpc][plane] +=
431  tpcgeom.PlanePitch(ip, ip + 1) / x_ticks_coefficient_gap[ip + 2];
432  }
433  x_ticks_offsets[cstat][tpc][plane] -=
434  tpcgeom.PlanePitch() * (1 / x_ticks_coefficient - 1 / x_ticks_coefficient_gap[1]);
435  }
436 
437  } // end if fIncludeInterPlanePitchInXTickOffsets
438 
439  // Add view dependent offset
440  // FIXME the offset should be plane-dependent
441  geo::View_t view = pgeom.View();
442  switch (view) {
443  case geo::kU: x_ticks_offsets[cstat][tpc][plane] += fTimeOffsetU; break;
444  case geo::kV: x_ticks_offsets[cstat][tpc][plane] += fTimeOffsetV; break;
445  case geo::kZ: x_ticks_offsets[cstat][tpc][plane] += fTimeOffsetZ; break;
446  case geo::kY: x_ticks_offsets[cstat][tpc][plane] += fTimeOffsetY; break;
447  case geo::kX: x_ticks_offsets[cstat][tpc][plane] += fTimeOffsetX; break;
448  default: throw cet::exception(__FUNCTION__) << "Bad view = " << view << "\n";
449  } // switch
450  }
451  }
452  }
453 
454  return DetectorPropertiesData{
455  *this, x_ticks_coefficient, move(x_ticks_offsets), move(drift_direction)};
456  }
457 
459  DetectorPropertiesStandard::CheckTimeOffsets(std::set<geo::View_t> const& requested_views) const
460  {
461  auto const& present_views = fGeo->Views();
462 
463  auto view_diff = [&present_views, &requested_views](geo::View_t const view) {
464  return static_cast<int>(present_views.count(view)) -
465  static_cast<int>(requested_views.count(view));
466  };
467 
468  // It is not an error to specify an offset if the view does not
469  // exist. However, if a view does exist, and an offset does not,
470  // then that will end the job.
471  std::ostringstream errors;
472  if (auto diff = view_diff(geo::kU); diff > 0) { errors << "TimeOffsetU missing for view U.\n"; }
473  if (auto diff = view_diff(geo::kV); diff > 0) { errors << "TimeOffsetV missing for view V.\n"; }
474  if (auto diff = view_diff(geo::kZ); diff > 0) { errors << "TimeOffsetZ missing for view Z.\n"; }
475  if (auto diff = view_diff(geo::kY); diff > 0) { errors << "TimeOffsetY missing for view Y.\n"; }
476  if (auto diff = view_diff(geo::kX); diff > 0) { errors << "TimeOffsetX missing for view X.\n"; }
477  return errors.str();
478  }
479 } // namespace
DetectorPropertiesStandard(fhicl::ParameterSet const &pset, const geo::GeometryCore *geo, const detinfo::LArProperties *lp, std::set< std::string > const &ignore_params={})
double PlanePitch(unsigned int p1=0, unsigned int p2=1) const
Definition: TPCGeo.cxx:388
double beta(double KE, const simb::MCParticle *part)
Encapsulate the construction of a single cyostat.
enum geo::_plane_proj View_t
Enumerate the possible plane projections.
std::string string
Definition: nybbler.cc:12
double Efield(unsigned int planegap=0) const override
kV/cm
Planes which measure V.
Definition: geo_types.h:130
unsigned int Nplanes() const
Number of planes in this tpc.
Definition: TPCGeo.h:165
void ValidateAndConfigure(fhicl::ParameterSet const &p, std::set< std::string > const &ignore_params)
Configures the provider, first validating the configuration.
std::set< geo::View_t > const & Views() const
Returns a list of possible views in the detector.
constexpr T pow(T x)
Definition: pow.h:72
double ElossVar(double mom, double mass) const override
Energy loss fluctuation ( )
Planes which measure X direction.
Definition: geo_types.h:134
Geometry information for a single TPC.
Definition: TPCGeo.h:38
double BirksCorrection(double dQdX) const override
dQ/dX in electrons/cm, returns dE/dX in MeV/cm.
unsigned int fNumberTimeSamples
number of clock ticks per event
double Temperature() const override
In kelvin.
virtual double Density() const
Returns argon density at the temperature from Temperature()
Planes which measure Z direction.
Definition: geo_types.h:132
string dir
Drift towards negative X values.
Definition: geo_types.h:162
unsigned int Ncryostats() const
Returns the number of cryostats in the detector.
constexpr T square(T x)
Definition: pow.h:21
DetectorPropertiesData DataFor(detinfo::DetectorClocksData const &clock_data) const override
Planes which measure Y direction.
Definition: geo_types.h:133
virtual double ExcitationEnergy() const =0
Mean excitation energy of the liquid (eV)
Planes which measure U.
Definition: geo_types.h:129
View_t View() const
Which coordinate does this plane measure.
Definition: PlaneGeo.h:184
virtual double AtomicMass() const =0
Atomic mass of the liquid (g/mol)
constexpr double kGeVToElectrons
23.6eV per ion pair, 1e9 eV/GeV
double dEdx(float dqdx, float Efield)
Definition: doAna.cpp:21
const double e
def key(type, name=None)
Definition: graph.py:13
static Config * config
Definition: config.cpp:1054
constexpr double kModBoxB
Modified Box Beta in g/(MeV cm²)*kV/cm.
def move(depos, offset)
Definition: depos.py:107
Geometry information for a single wire plane.The plane is represented in the geometry by a solid whic...
Definition: PlaneGeo.h:82
SternheimerParameters_t fSternheimerParameters
Sternheimer parameters.
p
Definition: test.py:223
unsigned int NTPC() const
Number of TPCs in this cryostat.
Definition: CryostatGeo.h:181
std::set< std::string > const & IgnorableProviderConfigKeys()
Returns a list of configuration keys that providers should ignore.
Definition: ProviderUtil.h:35
CryostatGeo const & Cryostat(geo::CryostatID const &cryoid) const
Returns the specified cryostat.
std::string CheckTimeOffsets(std::set< geo::View_t > const &requested_views) const
General LArSoft Utilities.
Description of geometry of one entire detector.
double gamma(double KE, const simb::MCParticle *part)
DriftDirection_t DriftDirection() const
Returns an enumerator value describing the drift direction.
Definition: TPCGeo.h:144
double ModBoxCorrection(double dQdX) const override
Encapsulate the construction of a single detector plane.
Contains all timing reference information for the detector.
const TPCGeo & TPC(unsigned int itpc) const
Return the itpc&#39;th TPC in the cryostat.
Definition: CryostatGeo.cxx:93
unsigned int fReadOutWindowSize
number of clock ticks per readout window
virtual double AtomicNumber() const =0
Atomic number of the liquid.
constexpr double kRecombk
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
int trigger_offset(DetectorClocksData const &data)
std::vector< double > fEfield
kV/cm (per inter-plane volume) !
Access the description of detector geometry.
list x
Definition: train.py:276
PlaneGeo const & Plane(geo::View_t view) const
Return the plane in the tpc with View_t view.
Definition: TPCGeo.cxx:263
constexpr double kRecombA
A constant.
double DriftVelocity(double efield=0., double temperature=0.) const override
cm/us
constexpr double kModBoxA
Modified Box Alpha.
double Wion
Definition: doAna.cpp:16
Collection of Physical constants used in LArSoft.
double sampling_rate(DetectorClocksData const &data)
Returns the period of the TPC readout electronics clock.
LArSoft geometry interface.
Definition: ChannelGeo.h:16
const double * PlaneLocation(unsigned int p) const
Definition: TPCGeo.cxx:382
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
Encapsulate the construction of a single detector plane.
double Eloss(double mom, double mass, double tcut) const override
Restricted mean energy loss (dE/dx)