LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
DetectorPropertiesStandard.cxx
Go to the documentation of this file.
1 
7 // Framework includes
8 
9 // LArSoft includes
11 #include "larcorealg/CoreUtils/ProviderUtil.h" // lar::IgnorableProviderConfigKeys()
16 
17 #include "cetlib/pow.h"
19 
20 // Art includes
21 #include "fhiclcpp/types/Table.h"
22 
23 // C/C++ libraries
24 #include <sstream> // std::ostringstream
25 
26 namespace detinfo {
27 
28  //--------------------------------------------------------------------
30  const geo::GeometryCore* geo,
31  const detinfo::LArProperties* lp,
32  std::set<std::string> const& ignore_params)
33  : fLP(lp), fGeo(geo)
34  {
35  ValidateAndConfigure(pset, ignore_params);
36  }
37 
38  //--------------------------------------------------------------------
40  std::set<std::string> const& ignore_params)
41  {
42  {
43  mf::LogInfo debug("setupProvider<DetectorPropertiesStandard>");
44 
45  debug << "Asked to ignore " << ignore_params.size() << " keys:";
46  for (auto const& key : ignore_params)
47  debug << " '" << key << "'";
48  }
49 
50  std::set<std::string> ignorable_keys = lar::IgnorableProviderConfigKeys();
51  ignorable_keys.insert(ignore_params.begin(), ignore_params.end());
52 
53  // parses and validates the parameter set:
54  fhicl::Table<Configuration_t> const config{p, ignorable_keys};
55 
56  fEfield = config().Efield();
57  fElectronlifetime = config().Electronlifetime();
58  fTemperature = config().Temperature();
59  fElectronsToADC = config().ElectronsToADC();
60  fNumberTimeSamples = config().NumberTimeSamples();
61  fReadOutWindowSize = config().ReadOutWindowSize();
62 
63  std::set<geo::View_t> present_views;
64  if (config().TimeOffsetU(fTimeOffsetU)) present_views.insert(geo::kU);
65  if (config().TimeOffsetV(fTimeOffsetV)) present_views.insert(geo::kV);
66  if (config().TimeOffsetZ(fTimeOffsetZ)) present_views.insert(geo::kZ);
67  if (config().TimeOffsetY(fTimeOffsetY)) present_views.insert(geo::kY);
68  if (config().TimeOffsetX(fTimeOffsetX)) present_views.insert(geo::kX);
69 
70  std::string const errors = CheckTimeOffsets(present_views);
71  if (!errors.empty()) {
72  throw cet::exception("DetectorPropertiesStandard") << "Detected configuration errors: \n"
73  << errors;
74  }
75 
76  fSternheimerParameters.a = config().SternheimerA();
77  fSternheimerParameters.k = config().SternheimerK();
78  fSternheimerParameters.x0 = config().SternheimerX0();
79  fSternheimerParameters.x1 = config().SternheimerX1();
80  fSternheimerParameters.cbar = config().SternheimerCbar();
81 
82  fDriftVelFudgeFactor = config().DriftVelFudgeFactor();
83 
84  fUseIcarusMicrobooneDriftModel = config().UseIcarusMicrobooneDriftModel();
85 
86  fIncludeInterPlanePitchInXTickOffsets = config().IncludeInterPlanePitchInXTickOffsets();
87 
88  fSimpleBoundary = config().SimpleBoundary();
89 
90  fModBoxA = config().ModBoxAlpha();
91  fModBoxB = config().ModBoxBeta();
92  }
93 
94  //------------------------------------------------------------------------------------//
95  double 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 DetectorPropertiesStandard::Density(double temperature) const
106  {
107  // Default temperature use internal value.
108  if (temperature == 0.) temperature = Temperature();
109 
110  return -0.00615 * temperature + 1.928;
111  }
112 
113  //----------------------------------------------------------------------------------
114  // Restricted mean energy loss (dE/dx) in units of MeV/cm.
115  //
116  // For unrestricted mean energy loss, set tcut = 0, or tcut large.
117  //
118  // Arguments:
119  //
120  // mom - Momentum of incident particle in GeV/c.
121  // mass - Mass of incident particle in GeV/c^2.
122  // tcut - Maximum kinetic energy of delta rays (MeV).
123  //
124  // Returned value is positive.
125  //
126  // Based on Bethe-Bloch formula as contained in particle data book.
127  // Material parameters (stored in larproperties.fcl) are taken from
128  // pdg web site http://pdg.lbl.gov/AtomicNuclearProperties/
129  //
130  double DetectorPropertiesStandard::Eloss(double mom, double mass, double tcut) const
131  {
132  // Some constants.
133  constexpr double K = 0.307075; // 4 pi N_A r_e^2 m_e c^2 (MeV cm^2/mol).
134  constexpr double me = 0.510998918; // Electron mass (MeV/c^2).
135 
136  // Calculate kinematic quantities.
137  double const bg = mom / mass; // beta*gamma.
138  double const gamma = sqrt(1. + bg * bg); // gamma.
139  double const beta = bg / gamma; // beta (velocity).
140  double const mer = 0.001 * me / mass; // electron mass / mass of incident particle.
141  double const tmax =
142  2. * me * bg * bg / (1. + 2. * gamma * mer + mer * mer); // Maximum delta ray energy (MeV).
143 
144  // Make sure tcut does not exceed tmax.
145  if (tcut == 0. || tcut > tmax) tcut = tmax;
146 
147  // Calculate density effect correction (delta).
148  double const x = std::log10(bg);
149  double delta = 0.;
150  if (x >= fSternheimerParameters.x0) {
151  delta = 2. * std::log(10.) * x - fSternheimerParameters.cbar;
152  if (x < fSternheimerParameters.x1)
153  delta += fSternheimerParameters.a *
155  }
156 
157  // Calculate stopping number.
158  double B =
159  0.5 * std::log(2. * me * bg * bg * tcut / (1.e-12 * cet::square(fLP->ExcitationEnergy()))) -
160  0.5 * beta * beta * (1. + tcut / tmax) - 0.5 * delta;
161 
162  // Don't let the stopping number become negative.
163  if (B < 1.) B = 1.;
164 
165  // Calculate dE/dx.
166  return Density() * K * fLP->AtomicNumber() * B / (fLP->AtomicMass() * beta * beta);
167  }
168 
169  //----------------------------------------------------------------------------------
170  double DetectorPropertiesStandard::ElossVar(double const mom, double const mass) const
171  {
172  // Some constants.
173  constexpr double K = 0.307075; // 4 pi N_A r_e^2 m_e c^2 (MeV cm^2/mol).
174  constexpr double me = 0.510998918; // Electron mass (MeV/c^2).
175 
176  // Calculate kinematic quantities.
177  double const bg = mom / mass; // beta*gamma.
178  double const gamma2 = 1. + bg * bg; // gamma^2.
179  double const beta2 = bg * bg / gamma2; // beta^2.
180  return gamma2 * (1. - 0.5 * beta2) * me * (fLP->AtomicNumber() / fLP->AtomicMass()) * K *
181  Density();
182  }
183 
184  //------------------------------------------------------------------------------------//
185  double DetectorPropertiesStandard::DriftVelocity(double efield, double temperature) const
186  {
187  // Drift Velocity as a function of Electric Field and LAr Temperature
188  // from : W. Walkowiak, NIM A 449 (2000) 288-294
189  //
190  // Option to use MicroBooNE+ICARUS model (as in arXiv:2008.09765) provided as
191  // well, with temperature depenence as prescribed by Mike Mooney based on
192  // looking at the Walkowiak data.
193  //
194  // Efield should have units of kV/cm
195  // Temperature should have units of Kelvin
196 
197  // Default Efield, use internal value.
198  if (efield == 0.) efield = Efield();
199 
200  if (efield > 4.0)
201  mf::LogWarning("DetectorPropertiesStandard")
202  << "DriftVelocity Warning! : E-field value of " << efield
203  << " kV/cm is outside of range covered by drift"
204  << " velocity parameterization. Returned value"
205  << " may not be correct";
206 
207  // Default temperature use internal value.
208  if (temperature == 0.) temperature = Temperature();
209 
210  if (temperature < 87.0 || temperature > 94.0)
211  mf::LogWarning("DetectorPropertiesStandard")
212  << "DriftVelocity Warning! : Temperature value of " << temperature
213  << " K is outside of range covered by drift velocity"
214  << " parameterization. Returned value may not be"
215  << " correct";
216 
217  double vd;
218 
220  double const tshift = -87.203 + temperature;
221  double const xFit = 0.0938163 - 0.0052563 * tshift - 0.0001470 * tshift * tshift;
222  double const uFit = 5.18406 + 0.01448 * tshift - 0.003497 * tshift * tshift -
223  0.000516 * tshift * tshift * tshift;
224 
225  // Icarus Parameter Set, use as default
226  constexpr double P1 = -0.04640; // K^-1
227  constexpr double P2 = 0.01712; // K^-1
228  constexpr double P3 = 1.88125; // (kV/cm)^-1
229  constexpr double P4 = 0.99408; // kV/cm
230  constexpr double P5 = 0.01172; // (kV/cm)^-P6
231  constexpr double P6 = 4.20214;
232  constexpr double T0 = 105.749; // K
233 
234  // Walkowiak Parameter Set
235  constexpr double P1W = -0.01481; // K^-1
236  constexpr double P2W = -0.0075; // K^-1
237  constexpr double P3W = 0.141; // (kV/cm)^-1
238  constexpr double P4W = 12.4; // kV/cm
239  constexpr double P5W = 1.627; // (kV/cm)^-P6
240  constexpr double P6W = 0.317;
241  constexpr double T0W = 90.371; // K
242 
243  // From Craig Thorne . . . currently not documented
244  // smooth transition from linear at small fields to
245  // icarus fit at most fields to Walkowiak at very high fields
246  if (efield < xFit)
247  vd = efield * uFit;
248  else if (efield < 0.619) {
249  vd = ((P1 * (temperature - T0) + 1) *
250  (P3 * efield * std::log(1 + P4 / efield) + P5 * std::pow(efield, P6)) +
251  P2 * (temperature - T0));
252  }
253  else if (efield < 0.699) {
254  vd = 12.5 * (efield - 0.619) *
255  ((P1W * (temperature - T0W) + 1) *
256  (P3W * efield * std::log(1 + P4W / efield) + P5W * std::pow(efield, P6W)) +
257  P2W * (temperature - T0W)) +
258  12.5 * (0.699 - efield) *
259  ((P1 * (temperature - T0) + 1) *
260  (P3 * efield * std::log(1 + P4 / efield) + P5 * std::pow(efield, P6)) +
261  P2 * (temperature - T0));
262  }
263  else {
264  vd = ((P1W * (temperature - T0W) + 1) *
265  (P3W * efield * std::log(1 + P4W / efield) + P5W * std::pow(efield, P6W)) +
266  P2W * (temperature - T0W));
267  }
268  }
269 
270  // MicroBooNE+ICARUS model (arXiv:2008.09765) with temperature dependence given by
271  // Mike Mooney based on looking at Walkowiak data (NIM A 449 (2000) 288-294)
273  constexpr double P0 = 0.;
274  constexpr double P1 = 5.53416;
275  constexpr double P2 = -6.53093;
276  constexpr double P3 = 3.20752;
277  constexpr double P4 = 0.389696;
278  constexpr double P5 = -0.556184;
279  vd = (1.0 - 0.0184 * (temperature - 89.0)) *
280  (P0 + P1 * cet::pow<1>(efield) + P2 * cet::pow<2>(efield) + P3 * cet::pow<3>(efield) +
281  P4 * cet::pow<4>(efield) + P5 * cet::pow<5>(efield));
282  }
283 
284  vd *= fDriftVelFudgeFactor / 10.;
285 
286  return vd; // in cm/us
287  }
288 
289  //----------------------------------------------------------------------------------
290  // The below function assumes that the user has applied the lifetime
291  // correction and effective pitch between the wires (usually after 3D
292  // reconstruction). Using with mean wire pitch will not give correct results.
293  // parameters:
294  // dQdX in electrons/cm, charge (amplitude or integral obtained) divided by
295  // effective pitch for a given 3D track.
296  // Electric Field in the drift region in KV/cm/
297  // returns dEdX in MeV/cm
299  {
300  return BirksCorrection(dQdx, Efield());
301  }
302  double DetectorPropertiesStandard::BirksCorrection(double dQdx, double E_field) const
303  {
304  // Correction for charge quenching using parameterization from
305  // S.Amoruso et al., NIM A 523 (2004) 275
306 
307  constexpr double A3t = util::kRecombA;
308  double K3t = util::kRecombk; // in KV/cm*(g/cm^2)/MeV
309  double const rho = Density(); // LAr density in g/cm^3
310  constexpr double Wion = 1000. / util::kGeVToElectrons; // 23.6 eV = 1e, Wion in MeV/e
311  K3t /= rho; // KV/MeV
312  double const dEdx = dQdx / (A3t / Wion - K3t / E_field * dQdx); // MeV/cm
313 
314  return dEdx;
315  }
316 
317  //----------------------------------------------------------------------------------
318  // Modified Box model correction
320  {
321  return ModBoxCorrection(dQdx, Efield());
322  }
323  double DetectorPropertiesStandard::ModBoxCorrection(double dQdx, double E_field) const
324  {
325  // Modified Box model correction has better behavior than the Birks
326  // correction at high values of dQ/dx.
327  double const rho = Density(); // LAr density in g/cm^3
328  constexpr double Wion = 1000. / util::kGeVToElectrons; // 23.6 eV = 1e, Wion in MeV/e
329  double const Beta = fModBoxB / (rho * E_field);
330  double const Alpha = fModBoxA;
331  double const dEdx = (exp(Beta * Wion * dQdx) - Alpha) / Beta;
332 
333  return dEdx;
334  }
335 
336  //--------------------------------------------------------------------
337  // x<--> ticks conversion methods
338  //
339  // Ben Jones April 2012,
340  // based on code by Herb Greenlee in SpacePointService
341  //
342 
343  //--------------------------------------------------------------------
344  // Recalculate x<-->ticks conversion parameters from detector constants
345 
347  detinfo::DetectorClocksData const& clock_data) const
348  {
349  double const samplingRate = sampling_rate(clock_data);
350  double const efield = Efield();
351  double const temperature = Temperature();
352  double const driftVelocity = DriftVelocity(efield, temperature);
353  double const x_ticks_coefficient = 0.001 * driftVelocity * samplingRate;
354 
355  double const triggerOffset = trigger_offset(clock_data);
356 
357  std::vector<std::vector<std::vector<double>>> x_ticks_offsets(fGeo->Ncryostats());
358  std::vector<std::vector<double>> drift_direction(fGeo->Ncryostats());
359 
360  for (size_t cstat = 0; cstat < fGeo->Ncryostats(); ++cstat) {
361  auto const& cryostat = fGeo->Cryostat(geo::CryostatID(cstat));
362  x_ticks_offsets[cstat].resize(cryostat.NTPC());
363  drift_direction[cstat].resize(cryostat.NTPC());
364 
365  for (size_t tpc = 0; tpc < cryostat.NTPC(); ++tpc) {
366  const geo::TPCGeo& tpcgeom = cryostat.TPC(tpc);
367 
368  const double dir((tpcgeom.DriftDirection() == geo::kNegX) ? +1.0 : -1.0);
369  drift_direction[cstat][tpc] = dir;
370 
371  int nplane = tpcgeom.Nplanes();
372  x_ticks_offsets[cstat][tpc].resize(nplane, 0.);
373  for (int plane = 0; plane < nplane; ++plane) {
374  const geo::PlaneGeo& pgeom = tpcgeom.Plane(plane);
375 
376  //Choose which plane to propagate to
377  //If accounting for the drift time between planes, start with the first plane,
378  //and iteratively add distances between planes
379  //Otherwise propagate straight to the last plane and
380  //assume a standard drift velocity (for wirecell recob::Wires)
381  unsigned int planeToPropagateTo =
382  (fIncludeInterPlanePitchInXTickOffsets ? 0 : tpcgeom.Nplanes() - 1);
383  // Calculate geometric time offset.
384  // only works if xyz[0]<=0
385  auto const xyz = tpcgeom.Plane(planeToPropagateTo).GetCenter();
386 
387  x_ticks_offsets[cstat][tpc][plane] =
388  -xyz.X() / (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) {
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  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
Float_t x
Definition: compare.C:6
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
Returns the center of the TPC volume in world coordinates [cm].
Definition: TPCGeo.cxx:361
Encapsulate the construction of a single cyostat.
Point_t const & GetCenter() const
Returns the centre of the wire plane in world coordinates [cm].
Definition: PlaneGeo.h:435
enum geo::_plane_proj View_t
Enumerate the possible plane projections.
double Efield(unsigned int planegap=0) const override
kV/cm
Planes which measure V.
Definition: geo_types.h:136
unsigned int Nplanes() const
Number of planes in this tpc.
Definition: TPCGeo.h:137
void ValidateAndConfigure(fhicl::ParameterSet const &p, std::set< std::string > const &ignore_params)
Configures the provider, first validating the configuration.
double ElossVar(double mom, double mass) const override
Energy loss fluctuation ( )
Planes which measure X direction.
Definition: geo_types.h:140
Geometry information for a single TPC.
Definition: TPCGeo.h:36
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:138
Drift towards negative X values.
Definition: geo_types.h:167
unsigned int Ncryostats() const
Returns the number of cryostats in the detector.
Definition: GeometryCore.h:430
CryostatGeo const & Cryostat(CryostatID const &cryoid=cryostat_zero) const
Returns the specified cryostat.
DetectorPropertiesData DataFor(detinfo::DetectorClocksData const &clock_data) const override
Planes which measure Y direction.
Definition: geo_types.h:139
virtual double ExcitationEnergy() const =0
Mean excitation energy of the liquid (eV)
Access the description of detector geometry.
Planes which measure U.
Definition: geo_types.h:135
View_t View() const
Which coordinate does this plane measure.
Definition: PlaneGeo.h:166
virtual double AtomicMass() const =0
Atomic mass of the liquid (g/mol)
constexpr double kGeVToElectrons
23.6eV per ion pair, 1e9 eV/GeV
DebugStuff debug
Definition: DebugStruct.cxx:4
Geometry information for a single wire plane.The plane is represented in the geometry by a solid whic...
Definition: PlaneGeo.h:78
SternheimerParameters_t fSternheimerParameters
Sternheimer parameters.
std::set< std::string > const & IgnorableProviderConfigKeys()
Returns a list of configuration keys that providers should ignore.
Definition: ProviderUtil.h:34
std::string CheckTimeOffsets(std::set< geo::View_t > const &requested_views) const
General LArSoft Utilities.
Description of geometry of one entire detector.
Definition: GeometryCore.h:119
DriftDirection_t DriftDirection() const
Returns an enumerator value describing the drift direction.
Definition: TPCGeo.h:121
float dEdx(detinfo::DetectorClocksData const &clockData, detinfo::DetectorPropertiesData const &detProp, const TCSlice &slc, TP3D &tp3d)
Definition: PFPUtils.cxx:2675
double ModBoxCorrection(double dQdX) const override
Encapsulate the construction of a single detector plane.
Contains all timing reference information for the detector.
TDirectory * dir
Definition: macro.C:5
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) !
std::set< View_t > const & Views() const
Returns a list of possible views in the detector.
Simple utilities for service providers.
PlaneGeo const & Plane(geo::View_t view) const
Return the plane in the tpc with View_t view.
Definition: TPCGeo.cxx:252
constexpr double kRecombA
A constant.
double DriftVelocity(double efield=0., double temperature=0.) const override
cm/us
Float_t e
Definition: plot.C:35
double sampling_rate(DetectorClocksData const &data)
Returns the period of the TPC readout electronics clock.
Namespace collecting geometry-related classes utilities.
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)
The data type to uniquely identify a cryostat.
Definition: geo_types.h:192