All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Classes | Public Types | Public Member Functions | Private Member Functions | Private Attributes | Friends | List of all members
larg4::LArVoxelReadout Class Reference

Transports energy depositions from GEANT4 to TPC channels. More...

#include <LArVoxelReadout.h>

Inheritance diagram for larg4::LArVoxelReadout:

Classes

struct  Setup_t
 Collection of what it takes to set a LArVoxelReadout up. More...
 

Public Types

typedef std::map< unsigned int,
sim::SimChannel
ChannelMap_t
 Type of map channel -> sim::SimChannel. More...
 

Public Member Functions

 LArVoxelReadout (std::string const &name)
 Constructor. Can detect which TPC to cover by the name. More...
 
 LArVoxelReadout (std::string const &name, unsigned int cryostat, unsigned int tpc)
 Constructor. Sets which TPC to work on. More...
 
void Setup (Setup_t const &setupData)
 Reads all the configuration elements from setupData More...
 
void SetSingleTPC (unsigned int cryostat, unsigned int tpc)
 Associates this readout to one specific TPC. More...
 
void SetDiscoverTPC ()
 Sets this readout to discover the TPC of each processed hit. More...
 
virtual void Initialize (G4HCofThisEvent *)
 
virtual void EndOfEvent (G4HCofThisEvent *)
 
virtual void clear ()
 
virtual G4bool ProcessHits (G4Step *, G4TouchableHistory *)
 
virtual void DrawAll ()
 
virtual void PrintAll ()
 
void ClearSimChannels ()
 
std::vector< sim::SimChannelGetSimChannels () const
 Creates a list with the accumulated information for the single TPC. More...
 
std::vector< sim::SimChannelGetSimChannels (unsigned short cryo, unsigned short tpc) const
 Creates a list with the accumulated information for specified TPC. More...
 
const ChannelMap_tGetSimChannelMap () const
 Returns the accumulated channel -> SimChannel map for the single TPC. More...
 
ChannelMap_tGetSimChannelMap ()
 
const ChannelMap_tGetSimChannelMap (unsigned short cryo, unsigned short tpc) const
 Returns the accumulated channel -> SimChannel map for the specified TPC. More...
 
ChannelMap_tGetSimChannelMap (unsigned short cryo, unsigned short tpc)
 

Private Member Functions

void SetClockData (detinfo::DetectorClocksData const *const clockData) noexcept
 
void SetPropertiesData (detinfo::DetectorPropertiesData const *const detProp) noexcept
 
void SetOffPlaneChargeRecoveryMargin (double margin)
 Sets the margin for recovery of charge drifted off-plane. More...
 
void SetRandomEngines (CLHEP::HepRandomEngine *pPropGen)
 Sets the random generators to be used. More...
 
geo::Point_t RecoverOffPlaneDeposit (geo::Point_t const &pos, geo::PlaneGeo const &plane) const
 Returns the point on the specified plane closest to position. More...
 
void DriftIonizationElectrons (detinfo::DetectorClocksData const &clockData, G4ThreeVector stepMidPoint, const double simTime, int trackID, unsigned short int cryostat, unsigned short int tpc, int origTrackID)
 
bool Has (std::vector< unsigned short int > v, unsigned short int tpc) const
 
void ProcessStep (G4Step *)
 

Private Attributes

double fDriftVelocity [3]
 
double fLongitudinalDiffusion
 
double fTransverseDiffusion
 
double fElectronLifetime
 
double fElectronClusterSize
 
int fMinNumberOfElCluster
 
bool fDontDriftThem
 
std::vector< unsigned short int > fSkipWireSignalInTPCs
 
double fOffPlaneMargin = 0.0
 Charge deposited within this many [cm] from the plane is lead onto it. More...
 
std::vector< std::vector
< ChannelMap_t > > 
fChannelMaps
 Maps of cryostat, tpc to channel data. More...
 
art::ServiceHandle
< geo::Geometry const > 
fGeoHandle
 Handle to the Geometry service. More...
 
art::ServiceHandle
< sim::LArG4Parameters const > 
fLgpHandle
 Handle to the LArG4 parameters service. More...
 
unsigned int fTPC
 which TPC this LArVoxelReadout corresponds to More...
 
unsigned int fCstat
 and in which cryostat (if bSingleTPC is true) More...
 
bool bSingleTPC
 true if this readout is associated with a single TPC More...
 
CLHEP::HepRandomEngine * fPropGen = nullptr
 random engine for charge propagation More...
 
detinfo::DetectorClocksData const * fClockData {nullptr}
 
detinfo::DetectorPropertiesData
const * 
fDetProp {nullptr}
 
G4ThreeVector fStepStart
 
G4ThreeVector fStepEnd
 
size_t fNSteps
 

Friends

class LArVoxelReadoutGeometry
 

Detailed Description

Transports energy depositions from GEANT4 to TPC channels.

This class acts on single energy depositions from GEANT4, simulating the transportation of the ensuing ionisation electrons to the readout channels:

  1. the number of ionisation electrons is read from the current larg4::IonizationAndScintillation instance
  2. space charge displacement is optionally applied
  3. lifetime correction is applied
  4. charge is split in small electron clusters
  5. each cluster is subject to longitudinal and transverse diffusion
  6. each cluster is assigned to one TPC channel for each wire plane
  7. optionally, charge is forced to stay on the planes; otherwise charge drifting outside the plane is lost

For each energy deposition, entries on the appropriate sim::SimChannel are added, with the information of the position where the energy deposit happened (in global coordinates, centimeters), the ID of the Geant4 track which produced the deposition, and the quantized time of arrival to the channel (in global TDC tick units). At most one entry is added for each electron cluster, but entries from the same energy deposit can be compacted if falling on the same TDC tick.

The main entry point of this class is the method ProcessHits().

Options

A few optional behaviours are supported:

Definition at line 170 of file LArVoxelReadout.h.

Member Typedef Documentation

typedef std::map<unsigned int, sim::SimChannel> larg4::LArVoxelReadout::ChannelMap_t

Type of map channel -> sim::SimChannel.

Definition at line 173 of file LArVoxelReadout.h.

Constructor & Destructor Documentation

larg4::LArVoxelReadout::LArVoxelReadout ( std::string const &  name)

Constructor. Can detect which TPC to cover by the name.

Definition at line 49 of file LArVoxelReadout.cxx.

49  : G4VSensitiveDetector(name)
50  {
51  // Initialize values for the electron-cluster calculation.
53 
54  // the standard name contains cryostat and TPC;
55  // if we don't find it, we will detect the TPC at each Geant hit
56  unsigned int cryostat, tpc;
57  if (std::sscanf(name.c_str(), "%*19s%1u%*4s%u", &cryostat, &tpc) == 2)
58  SetSingleTPC(cryostat, tpc);
59  else
61 
62  } // LArVoxelReadout::LArVoxelReadout()
void SetSingleTPC(unsigned int cryostat, unsigned int tpc)
Associates this readout to one specific TPC.
void SetDiscoverTPC()
Sets this readout to discover the TPC of each processed hit.
then echo fcl name
larg4::LArVoxelReadout::LArVoxelReadout ( std::string const &  name,
unsigned int  cryostat,
unsigned int  tpc 
)

Constructor. Sets which TPC to work on.

Definition at line 67 of file LArVoxelReadout.cxx.

69  {
70  SetSingleTPC(cryostat, tpc);
71  }
LArVoxelReadout(std::string const &name)
Constructor. Can detect which TPC to cover by the name.
void SetSingleTPC(unsigned int cryostat, unsigned int tpc)
Associates this readout to one specific TPC.
then echo fcl name

Member Function Documentation

void larg4::LArVoxelReadout::clear ( )
virtual

Definition at line 146 of file LArVoxelReadout.cxx.

147  {}
void larg4::LArVoxelReadout::ClearSimChannels ( )

Definition at line 151 of file LArVoxelReadout.cxx.

152  {
153  fChannelMaps.resize(fGeoHandle->Ncryostats());
154  size_t cryo = 0;
155  for (auto& cryoData : fChannelMaps) { // each, a vector of maps
156  cryoData.resize(fGeoHandle->NTPC(cryo++));
157  for (auto& channelsMap : cryoData)
158  channelsMap.clear(); // each, a map
159  } // for cryostats
160  } // LArVoxelReadout::ClearSimChannels()
art::ServiceHandle< geo::Geometry const > fGeoHandle
Handle to the Geometry service.
std::vector< std::vector< ChannelMap_t > > fChannelMaps
Maps of cryostat, tpc to channel data.
void larg4::LArVoxelReadout::DrawAll ( )
virtual

Definition at line 595 of file LArVoxelReadout.cxx.

596  {}
void larg4::LArVoxelReadout::DriftIonizationElectrons ( detinfo::DetectorClocksData const &  clockData,
G4ThreeVector  stepMidPoint,
const double  simTime,
int  trackID,
unsigned short int  cryostat,
unsigned short int  tpc,
int  origTrackID 
)
private
Todo:
think about effects of drift between planes
Todo:
think about effects of drift between planes
Todo:
check on what happens if we allow the tdc value to be
Todo:
beyond the end of the expected number of ticks

Definition at line 340 of file LArVoxelReadout.cxx.

347  {
348  auto const tpcClock = clockData.TPCClock();
349 
350  // this must be always true, unless caller has been sloppy
351  assert(fPropGen); // No propagation random generator provided?!
352 
353  CLHEP::RandGauss PropRand(*fPropGen);
354 
355  // This routine gets called frequently, once per every particle
356  // traveling through every voxel. Use whatever tricks we can to
357  // increase its execution speed.
358 
359  static double LifetimeCorr_const = -1000. * fElectronLifetime;
360  static double LDiff_const = std::sqrt(2. * fLongitudinalDiffusion);
361  static double TDiff_const = std::sqrt(2. * fTransverseDiffusion);
362  static double RecipDriftVel[3] = {
363  1. / fDriftVelocity[0], 1. / fDriftVelocity[1], 1. / fDriftVelocity[2]};
364 
365  struct Deposit_t {
366  double energy = 0.;
367  double electrons = 0.;
368 
369  void
370  add(double more_energy, double more_electrons)
371  {
372  energy += more_energy;
373  electrons += more_electrons;
374  }
375  }; // Deposit_t
376 
377  // Map of electrons to store - catalogued by map[channel][tdc]
378  std::map<raw::ChannelID_t, std::map<unsigned int, Deposit_t>> DepositsToStore;
379 
380  double xyz1[3] = {0.};
381 
382  double const xyz[3] = {
383  stepMidPoint.x() / CLHEP::cm, stepMidPoint.y() / CLHEP::cm, stepMidPoint.z() / CLHEP::cm};
384 
385  // Already know which TPC we're in because we have been told
386 
387  try {
388  const geo::TPCGeo& tpcg = fGeoHandle->TPC(tpc, cryostat);
389 
390  // X drift distance - the drift direction can be either in
391  // the positive or negative direction, so use std::abs
392 
393  /// \todo think about effects of drift between planes
394  double XDrift = std::abs(stepMidPoint.x() / CLHEP::cm - tpcg.PlaneLocation(0)[0]);
395  //std::cout<<tpcg.DriftDirection()<<std::endl;
396  if (tpcg.DriftDirection() == geo::kNegX)
397  XDrift = stepMidPoint.x() / CLHEP::cm - tpcg.PlaneLocation(0)[0];
398  else if (tpcg.DriftDirection() == geo::kPosX)
399  XDrift = tpcg.PlaneLocation(0)[0] - stepMidPoint.x() / CLHEP::cm;
400 
401  if (XDrift < 0.) return;
402 
403  // Get SCE {x,y,z} offsets for particular location in TPC
404  geo::Vector_t posOffsets;
405  auto const* SCE = lar::providerFrom<spacecharge::SpaceChargeService>();
406  if (SCE->EnableSimSpatialSCE() == true) {
407  posOffsets = SCE->GetPosOffsets({xyz[0], xyz[1], xyz[2]});
408  if (larsim::Utils::SCE::out_of_bounds(posOffsets)) {
409  return;
410  }
411  }
412  posOffsets.SetX(-posOffsets.X());
413 
414  // Drift time (nano-sec)
415  double TDrift;
416  XDrift += posOffsets.X();
417 
418  // Space charge distortion could push the energy deposit beyond the wire
419  // plane (see issue #15131). Given that we don't have any subtlety in the
420  // simulation of this region, bringing the deposit exactly on the plane
421  // should be enough for the time being.
422  if (XDrift < 0.) XDrift = 0.;
423 
424  TDrift = XDrift * RecipDriftVel[0];
425  if (tpcg.Nplanes() == 2) { // special case for ArgoNeuT (plane 0 is the second wire plane)
426  TDrift = ((XDrift - tpcg.PlanePitch(0, 1)) * RecipDriftVel[0] +
427  tpcg.PlanePitch(0, 1) * RecipDriftVel[1]);
428  }
429 
430  const double lifetimecorrection = TMath::Exp(TDrift / LifetimeCorr_const);
431  const int nIonizedElectrons =
434 
435  // if we have no electrons (too small energy or too large recombination)
436  // we are done already here
437  if (nIonizedElectrons <= 0) {
438  MF_LOG_DEBUG("LArVoxelReadout")
439  << "No electrons drifted to readout, " << energy << " MeV lost.";
440  return;
441  }
442  // includes the effect of lifetime
443  const double nElectrons = nIonizedElectrons * lifetimecorrection;
444 
445  // Longitudinal & transverse diffusion sigma (cm)
446  double SqrtT = std::sqrt(TDrift);
447  double LDiffSig = SqrtT * LDiff_const;
448  double TDiffSig = SqrtT * TDiff_const;
449  double electronclsize = fElectronClusterSize;
450 
451  int nClus = (int)std::ceil(nElectrons / electronclsize);
452  if (nClus < fMinNumberOfElCluster) {
453  electronclsize = nElectrons / fMinNumberOfElCluster;
454  if (electronclsize < 1.0) { electronclsize = 1.0; }
455  nClus = (int)std::ceil(nElectrons / electronclsize);
456  }
457 
458  // Compute arrays of values as quickly as possible.
459  std::vector<double> XDiff(nClus);
460  std::vector<double> YDiff(nClus);
461  std::vector<double> ZDiff(nClus);
462  std::vector<double> nElDiff(nClus, electronclsize);
463  std::vector<double> nEnDiff(nClus);
464 
465  // fix the number of electrons in the last cluster, that has smaller size
466  nElDiff.back() = nElectrons - (nClus - 1) * electronclsize;
467 
468  for (size_t xx = 0; xx < nElDiff.size(); ++xx) {
469  if (nElectrons > 0)
470  nEnDiff[xx] = energy / nElectrons * nElDiff[xx];
471  else
472  nEnDiff[xx] = 0.;
473  }
474 
475  double const avegageYtransversePos = (stepMidPoint.y() / CLHEP::cm) + posOffsets.Y();
476  double const avegageZtransversePos = (stepMidPoint.z() / CLHEP::cm) + posOffsets.Z();
477 
478  // Smear drift times by x position and drift time
479  if (LDiffSig > 0.0)
480  PropRand.fireArray(nClus, &XDiff[0], 0., LDiffSig);
481  else
482  XDiff.assign(nClus, 0.0);
483 
484  if (TDiffSig > 0.0) {
485  // Smear the Y,Z position by the transverse diffusion
486  PropRand.fireArray(nClus, &YDiff[0], avegageYtransversePos, TDiffSig);
487  PropRand.fireArray(nClus, &ZDiff[0], avegageZtransversePos, TDiffSig);
488  }
489  else {
490  YDiff.assign(nClus, avegageYtransversePos);
491  ZDiff.assign(nClus, avegageZtransversePos);
492  }
493 
494  // make a collection of electrons for each plane
495  for (size_t p = 0; p < tpcg.Nplanes(); ++p) {
496 
497  geo::PlaneGeo const& plane = tpcg.Plane(p);
498 
499  double Plane0Pitch = tpcg.Plane0Pitch(p);
500 
501  // "-" sign is because Plane0Pitch output is positive. Andrzej
502  xyz1[0] = tpcg.PlaneLocation(0)[0] - Plane0Pitch;
503 
504  // Drift nClus electron clusters to the induction plane
505  for (int k = 0; k < nClus; ++k) {
506  // Correct drift time for longitudinal diffusion and plane
507  double TDiff = TDrift + XDiff[k] * RecipDriftVel[0];
508  // Take into account different Efields between planes
509  // Also take into account special case for ArgoNeuT where Nplanes = 2.
510  for (size_t ip = 0; ip < p; ++ip) {
511  TDiff +=
512  tpcg.PlanePitch(ip, ip + 1) * RecipDriftVel[tpcg.Nplanes() == 3 ? ip + 1 : ip + 2];
513  }
514  xyz1[1] = YDiff[k];
515  xyz1[2] = ZDiff[k];
516 
517  /// \todo think about effects of drift between planes
518 
519  // grab the nearest channel to the xyz1 position
520  try {
521  if (fOffPlaneMargin != 0) {
522  // get the effective position where to consider the charge landed;
523  //
524  // Some optimisations are possible; in particular, this method
525  // could be extended to inform us if the point was too far.
526  // Currently, if that is the case the code will proceed, find the
527  // point is off plane, emit a warning and skip the deposition.
528  //
529  auto const landingPos = RecoverOffPlaneDeposit({xyz1[0], xyz1[1], xyz1[2]}, plane);
530  xyz1[0] = landingPos.X();
531  xyz1[1] = landingPos.Y();
532  xyz1[2] = landingPos.Z();
533 
534  } // if charge lands off plane
535  uint32_t channel = fGeoHandle->NearestChannel(xyz1, p, tpc, cryostat);
536 
537  /// \todo check on what happens if we allow the tdc value to be
538  /// \todo beyond the end of the expected number of ticks
539  // Add potential decay/capture/etc delay effect, simTime.
540  unsigned int tdc = tpcClock.Ticks(clockData.G4ToElecTime(TDiff + simTime));
541 
542  // Add electrons produced by each cluster to the map
543  DepositsToStore[channel][tdc].add(nEnDiff[k], nElDiff[k]);
544  }
545  catch (cet::exception& e) {
546  MF_LOG_DEBUG("LArVoxelReadout")
547  << "unable to drift electrons from point (" << xyz[0] << "," << xyz[1] << ","
548  << xyz[2] << ") with exception " << e;
549  }
550  } // end loop over clusters
551  } // end loop over planes
552 
553  // Now store them in SimChannels
554  ChannelMap_t& ChannelDataMap = fChannelMaps[cryostat][tpc];
555 
556  // browse deposited data on each channel: (channel; deposit data in time)
557  for (auto const& deposit_per_channel : DepositsToStore) {
558 
559  raw::ChannelID_t channel = deposit_per_channel.first;
560 
561  // find whether we already have this channel
562  auto iChannelData = ChannelDataMap.find(channel);
563 
564  // channelData is the SimChannel these deposits are going to be added to
565  // If there is such a channel already, use it (first beanch).
566  // If it's a new channel, the inner assignment creates a new SimChannel
567  // in the map, and we save its reference in channelData
568  sim::SimChannel& channelData = (iChannelData == ChannelDataMap.end()) ?
569  (ChannelDataMap[channel] = sim::SimChannel(channel)) :
570  iChannelData->second;
571 
572  // go through all deposits, one for each TDC: (TDC, deposit data)
573  for (auto const& deposit_per_tdc : deposit_per_channel.second) {
574  channelData.AddIonizationElectrons(trackID,
575  deposit_per_tdc.first,
576  deposit_per_tdc.second.electrons,
577  xyz,
578  deposit_per_tdc.second.energy,
579  origTrackID);
580 
581  } // for deposit on TDCs
582  } // for deposit on channels
583 
584  } // end try intended to catch points where TPC can't be found
585  catch (cet::exception& e) {
586  MF_LOG_DEBUG("LArVoxelReadout") << "step cannot be found in a TPC\n" << e;
587  }
588 
589  return;
590  }
ROOT::Math::DisplacementVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Vector_t
Type for representation of momenta in 3D space.
Definition: geo_vectors.h:164
double PlanePitch(unsigned int p1=0, unsigned int p2=1) const
Definition: TPCGeo.cxx:388
Energy deposited on a readout channel by simulated tracks.
Definition: SimChannel.h:145
bool out_of_bounds(geo::Vector_t const &offset)
unsigned int Nplanes() const
Number of planes in this tpc.
Definition: TPCGeo.h:165
art::ServiceHandle< geo::Geometry const > fGeoHandle
Handle to the Geometry service.
pdgs p
Definition: selectors.fcl:22
Geometry information for a single TPC.
Definition: TPCGeo.h:38
Drift towards negative X values.
Definition: geo_types.h:162
geo::Point_t RecoverOffPlaneDeposit(geo::Point_t const &pos, geo::PlaneGeo const &plane) const
Returns the point on the specified plane closest to position.
T abs(T value)
std::map< unsigned int, sim::SimChannel > ChannelMap_t
Type of map channel -&gt; sim::SimChannel.
for($it=0;$it< $RaceTrack_number;$it++)
Geometry information for a single wire plane.The plane is represented in the geometry by a solid whic...
Definition: PlaneGeo.h:82
static IonizationAndScintillation * Instance()
double Plane0Pitch(unsigned int p) const
Definition: TPCGeo.cxx:324
DriftDirection_t DriftDirection() const
Returns an enumerator value describing the drift direction.
Definition: TPCGeo.h:144
std::vector< std::vector< ChannelMap_t > > fChannelMaps
Maps of cryostat, tpc to channel data.
double fOffPlaneMargin
Charge deposited within this many [cm] from the plane is lead onto it.
Drift towards positive X values.
Definition: geo_types.h:161
CLHEP::HepRandomEngine * fPropGen
random engine for charge propagation
do i e
PlaneGeo const & Plane(geo::View_t view) const
Return the plane in the tpc with View_t view.
Definition: TPCGeo.cxx:263
void AddIonizationElectrons(TrackID_t trackID, TDC_t tdc, double numberElectrons, double const *xyz, double energy, TrackID_t origTrackID=util::kBogusI)
Add ionization electrons and energy to this channel.
Definition: SimChannel.cxx:55
pdgs k
Definition: selectors.fcl:22
unsigned int ChannelID_t
Type representing the ID of a readout channel.
Definition: RawTypes.h:28
const double * PlaneLocation(unsigned int p) const
Definition: TPCGeo.cxx:382
void larg4::LArVoxelReadout::EndOfEvent ( G4HCofThisEvent *  )
virtual

Definition at line 139 of file LArVoxelReadout.cxx.

140  {
141  MF_LOG_DEBUG("LArVoxelReadout") << "Total number of steps was " << fNSteps << std::endl;
142  }
const LArVoxelReadout::ChannelMap_t & larg4::LArVoxelReadout::GetSimChannelMap ( ) const

Returns the accumulated channel -> SimChannel map for the single TPC.

Definition at line 163 of file LArVoxelReadout.cxx.

164  {
165  if (bSingleTPC) return GetSimChannelMap(fCstat, fTPC);
166  throw cet::exception("LArVoxelReadout") << "TPC not specified";
167  }
unsigned int fTPC
which TPC this LArVoxelReadout corresponds to
const ChannelMap_t & GetSimChannelMap() const
Returns the accumulated channel -&gt; SimChannel map for the single TPC.
bool bSingleTPC
true if this readout is associated with a single TPC
unsigned int fCstat
and in which cryostat (if bSingleTPC is true)
LArVoxelReadout::ChannelMap_t & larg4::LArVoxelReadout::GetSimChannelMap ( )

Definition at line 170 of file LArVoxelReadout.cxx.

171  {
172  if (bSingleTPC) return GetSimChannelMap(fCstat, fTPC);
173  throw cet::exception("LArVoxelReadout") << "TPC not specified";
174  }
unsigned int fTPC
which TPC this LArVoxelReadout corresponds to
const ChannelMap_t & GetSimChannelMap() const
Returns the accumulated channel -&gt; SimChannel map for the single TPC.
bool bSingleTPC
true if this readout is associated with a single TPC
unsigned int fCstat
and in which cryostat (if bSingleTPC is true)
const LArVoxelReadout::ChannelMap_t & larg4::LArVoxelReadout::GetSimChannelMap ( unsigned short  cryo,
unsigned short  tpc 
) const

Returns the accumulated channel -> SimChannel map for the specified TPC.

Definition at line 177 of file LArVoxelReadout.cxx.

178  {
179  return fChannelMaps.at(cryo).at(tpc);
180  }
std::vector< std::vector< ChannelMap_t > > fChannelMaps
Maps of cryostat, tpc to channel data.
LArVoxelReadout::ChannelMap_t & larg4::LArVoxelReadout::GetSimChannelMap ( unsigned short  cryo,
unsigned short  tpc 
)

Definition at line 183 of file LArVoxelReadout.cxx.

184  {
185  return fChannelMaps.at(cryo).at(tpc);
186  }
std::vector< std::vector< ChannelMap_t > > fChannelMaps
Maps of cryostat, tpc to channel data.
std::vector< sim::SimChannel > larg4::LArVoxelReadout::GetSimChannels ( ) const

Creates a list with the accumulated information for the single TPC.

Definition at line 189 of file LArVoxelReadout.cxx.

190  {
191  if (bSingleTPC) return GetSimChannels(fCstat, fTPC);
192  throw cet::exception("LArVoxelReadout") << "TPC not specified";
193  }
unsigned int fTPC
which TPC this LArVoxelReadout corresponds to
bool bSingleTPC
true if this readout is associated with a single TPC
std::vector< sim::SimChannel > GetSimChannels() const
Creates a list with the accumulated information for the single TPC.
unsigned int fCstat
and in which cryostat (if bSingleTPC is true)
std::vector< sim::SimChannel > larg4::LArVoxelReadout::GetSimChannels ( unsigned short  cryo,
unsigned short  tpc 
) const

Creates a list with the accumulated information for specified TPC.

Definition at line 196 of file LArVoxelReadout.cxx.

197  {
198  std::vector<sim::SimChannel> channels;
199  const ChannelMap_t& chmap = fChannelMaps.at(cryo).at(tpc);
200  channels.reserve(chmap.size());
201  for (const auto& chpair : chmap)
202  channels.push_back(chpair.second);
203  return channels;
204  }
std::map< unsigned int, sim::SimChannel > ChannelMap_t
Type of map channel -&gt; sim::SimChannel.
std::vector< std::vector< ChannelMap_t > > fChannelMaps
Maps of cryostat, tpc to channel data.
bool larg4::LArVoxelReadout::Has ( std::vector< unsigned short int >  v,
unsigned short int  tpc 
) const
inlineprivate

Definition at line 329 of file LArVoxelReadout.h.

330  {
331  for (auto c : v)
332  if (c == tpc) return true;
333  return false;
334  }
void larg4::LArVoxelReadout::Initialize ( G4HCofThisEvent *  )
virtual

Definition at line 103 of file LArVoxelReadout.cxx.

104  {
105  assert(fClockData != nullptr &&
106  "You must use set the clock data pointer at the beginning "
107  "of each module's event-level call. This might be done through the "
108  "LArVoxelReadoutGeometry::Sentry class.");
109  assert(fDetProp != nullptr &&
110  "You must use set the detector-properties data pointer at the beginning "
111  "of each module's event-level call. This might be done through the "
112  "LArVoxelReadoutGeometry::Sentry class.");
113 
115  for (int i = 0; i < 3; ++i)
116  fDriftVelocity[i] =
118 
119  fElectronClusterSize = fLgpHandle->ElectronClusterSize();
120  fMinNumberOfElCluster = fLgpHandle->MinNumberOfElCluster();
121  fLongitudinalDiffusion = fLgpHandle->LongitudinalDiffusion();
122  fTransverseDiffusion = fLgpHandle->TransverseDiffusion();
123  fDontDriftThem = fLgpHandle->DisableWireplanes();
124  fSkipWireSignalInTPCs = fLgpHandle->SkipWireSignalInTPCs();
125 
126  MF_LOG_DEBUG("LArVoxelReadout")
127  << " e lifetime: " << fElectronLifetime << "\n Temperature: " << fDetProp->Temperature()
128  << "\n Drift velocity: " << fDriftVelocity[0] << " " << fDriftVelocity[1] << " "
129  << fDriftVelocity[2];
130 
131  fDontDriftThem = (fDontDriftThem || fLgpHandle->NoElectronPropagation());
132 
133  fNSteps = 0;
134  }
art::ServiceHandle< sim::LArG4Parameters const > fLgpHandle
Handle to the LArG4 parameters service.
double Temperature() const
In kelvin.
detinfo::DetectorClocksData const * fClockData
double Efield(unsigned int planegap=0) const
kV/cm
std::vector< unsigned short int > fSkipWireSignalInTPCs
detinfo::DetectorPropertiesData const * fDetProp
double DriftVelocity(double efield=0., double temperature=0.) const
cm/us
void larg4::LArVoxelReadout::PrintAll ( )
virtual

Definition at line 598 of file LArVoxelReadout.cxx.

599  {}
G4bool larg4::LArVoxelReadout::ProcessHits ( G4Step *  step,
G4TouchableHistory *  pHistory 
)
virtual

Definition at line 209 of file LArVoxelReadout.cxx.

210  {
211  // All work done for the "parallel world" "box of voxels" in
212  // LArVoxelReadoutGeometry makes this a fairly simple routine.
213  // First, the usual check for non-zero energy:
214 
215  // Only process the hit if the step is inside the active volume and
216  // it has deposited energy. The hit being inside the active volume
217  // is virtually sure to happen because the LArVoxelReadoutGeometry
218  // that this class makes use of only has voxels for inside the TPC.
219 
220  // The step can be no bigger than the size of the voxel,
221  // because of the geometry set up in LArVoxelGeometry and the
222  // transportation set up in PhysicsList. Find the mid-point
223  // of the step.
224 
225  if (step->GetTotalEnergyDeposit() > 0) {
226 
227  // Make sure we have the IonizationAndScintillation singleton
228  // reset to this step
230  fNSteps++;
231  if (!fDontDriftThem) {
232 
233  G4ThreeVector midPoint =
234  0.5 * (step->GetPreStepPoint()->GetPosition() + step->GetPostStepPoint()->GetPosition());
235  double g4time = step->GetPreStepPoint()->GetGlobalTime();
236 
237  // Find the Geant4 track ID for the particle responsible for depositing the
238  // energy. if we are only storing primary EM shower particles, and this energy
239  // is from a secondary etc EM shower particle, the ID returned is the primary
240  const int trackID = ParticleListAction::GetCurrentTrackID();
241  // For all particles but shower daughters, origTrackID is the same as trackID.
242  // For shower daughters it contains their original trackID instead of the
243  // shower primary's trackID.
244  const int origTrackID = ParticleListAction::GetCurrentOrigTrackID();
245 
246  // Find out which TPC we are in.
247  // If this readout object covers just one, we already know it.
248  // Otherwise, we have to ask Geant where we are.
249  unsigned short int cryostat = 0, tpc = 0;
250  if (bSingleTPC) {
251  cryostat = fCstat;
252  tpc = fTPC;
253  }
254  else {
255  // detect the TPC we are in
256  const G4VTouchable* pTouchable = step->GetPreStepPoint()->GetTouchable();
257  if (!pTouchable) {
258  throw cet::exception("LArG4") << "Untouchable step in LArVoxelReadout::ProcessHits()";
259  }
260 
261  // one of the ancestors of the touched volume is supposed to be
262  // actually a G4PVPlacementInTPC that knows which TPC it covers;
263  // currently, it's the 4th in the ladder:
264  // [0] voxel [1] voxel tower [2] voxel plane [3] the full box;
265  G4int depth = 0;
266  while (depth < pTouchable->GetHistoryDepth()) {
267  const G4PVPlacementInTPC* pPVinTPC =
268  dynamic_cast<const G4PVPlacementInTPC*>(pTouchable->GetVolume(depth++));
269  if (!pPVinTPC) continue;
270  cryostat = pPVinTPC->ID.Cryostat;
271  tpc = pPVinTPC->ID.TPC;
272  if (Has(fSkipWireSignalInTPCs, tpc)) { return true; }
273  break;
274  } // while
275  if (depth < pTouchable->GetHistoryDepth()) {
276  // this is a fundamental error where the step does not happen in
277  // any TPC; this should not happen in the readout geometry!
278  throw cet::exception("LArG4") << "No TPC ID found in LArVoxelReadout::ProcessHits()";
279  } // if
280  MF_LOG_DEBUG("LArVoxelReadoutHit") << " hit in C=" << cryostat << " T=" << tpc;
281  } // if more than one TPC
282 
283  // Note that if there is no particle ID for this energy deposit, the
284  // trackID will be sim::NoParticleId.
285 
286  DriftIonizationElectrons(*fClockData, midPoint, g4time, trackID, cryostat, tpc, origTrackID);
287  } // end we are drifting
288  } // end there is non-zero energy deposition
289 
290  return true;
291  }
unsigned int fTPC
which TPC this LArVoxelReadout corresponds to
detinfo::DetectorClocksData const * fClockData
bool bSingleTPC
true if this readout is associated with a single TPC
std::vector< unsigned short int > fSkipWireSignalInTPCs
void DriftIonizationElectrons(detinfo::DetectorClocksData const &clockData, G4ThreeVector stepMidPoint, const double simTime, int trackID, unsigned short int cryostat, unsigned short int tpc, int origTrackID)
static IonizationAndScintillation * Instance()
G4PVPlacementWithID< TPCID_t > G4PVPlacementInTPC
A physical volume with a TPC ID.
bool Has(std::vector< unsigned short int > v, unsigned short int tpc) const
unsigned int fCstat
and in which cryostat (if bSingleTPC is true)
void larg4::LArVoxelReadout::ProcessStep ( G4Step *  )
private
geo::Point_t larg4::LArVoxelReadout::RecoverOffPlaneDeposit ( geo::Point_t const &  pos,
geo::PlaneGeo const &  plane 
) const
private

Returns the point on the specified plane closest to position.

Parameters
posthe position to be tested (global coordinates, centimeters)
planethe plane to test the position against
Returns
a position on plane, unless pos is too far from it

This method considers the distance of the position pos from the active part of the plane (see geo::Plane::DeltaFromActivePlane()). If the position is less than a configurable margin far from the plane, the closest point on the plane to that position is returned. Otherwise, the position itself is returned.

Ionization charge may be drifted so that when it arrives to the plane, it actually does not hit the area covered by wires. This can happen for many reasons:

  • space charge distortion led the point outside the fiducial volume (this may be prevented by specific code)
  • diffusion pushes the charge outside the instrumented region
  • the geometry of the wire planes is such that planes have different coverage and what one plane can cover, the next can't

The "recovery" consists in forcing the charge to the instrumented area covered by the plane wires. The distance of the drifted charge from each plane border is computed and compared to the margin. If that distance is smaller than the margin, it is neglected and the charge is assigned a new position on that border.

This method provides the position that should be used for the charge deposition.

This is a simplistic approach to the simulation of border effects, assuming that in fact the electric field, which is continuous and pointing to the collection wires, will drive the charge to the wires even when they are "off track". No correction is applied for the additional time that such deviation would take.

Definition at line 303 of file LArVoxelReadout.cxx.

304  {
305  //
306  // translate the landing position on the two frame coordinates
307  // ("width" and "depth")
308  //
309  auto const landingPos = plane.PointWidthDepthProjection(pos);
310 
311  //
312  // compute the distance of the landing position on the two frame
313  // coordinates ("width" and "depth");
314  // keep the point within 10 micrometers (0.001 cm) from the border
315  //
316  auto const offPlane = plane.DeltaFromActivePlane(landingPos, 0.001);
317 
318  //
319  // if both the distances are below the margin, move the point to
320  // the border
321  //
322 
323  // nothing to recover: landing is inside
324  if ((offPlane.X() == 0.0) && (offPlane.Y() == 0.0)) return pos;
325 
326  // won't recover: too far
327  if ((std::abs(offPlane.X()) > fOffPlaneMargin) || (std::abs(offPlane.Y()) > fOffPlaneMargin))
328  return pos;
329 
330  // we didn't fully decompose because it might be unnecessary;
331  // now we need the full thing
332  auto const distance = plane.DistanceFromPlane(pos);
333 
334  return plane.ComposePoint<geo::Point_t>(distance, landingPos + offPlane);
335  } // LArVoxelReadout::RecoverOffPlaneDeposit()
T abs(T value)
double distance(geo::Point_t const &point, CathodeDesc_t const &cathode)
Returns the distance of a point from the cathode.
double fOffPlaneMargin
Charge deposited within this many [cm] from the plane is lead onto it.
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
Definition: geo_vectors.h:184
void larg4::LArVoxelReadout::SetClockData ( detinfo::DetectorClocksData const *const  clockData)
inlineprivatenoexcept

Definition at line 251 of file LArVoxelReadout.h.

252  {
253  fClockData = clockData;
254  }
detinfo::DetectorClocksData const * fClockData
void larg4::LArVoxelReadout::SetDiscoverTPC ( )

Sets this readout to discover the TPC of each processed hit.

Definition at line 92 of file LArVoxelReadout.cxx.

93  {
94  bSingleTPC = false;
95  fCstat = 0;
96  fTPC = 0;
97  MF_LOG_DEBUG("LArVoxelReadout") << GetName() << " autodetects TPC";
98  }
unsigned int fTPC
which TPC this LArVoxelReadout corresponds to
bool bSingleTPC
true if this readout is associated with a single TPC
unsigned int fCstat
and in which cryostat (if bSingleTPC is true)
void larg4::LArVoxelReadout::SetOffPlaneChargeRecoveryMargin ( double  margin)
inlineprivate

Sets the margin for recovery of charge drifted off-plane.

Parameters
marginthe extent of the margin on each frame coordinate [cm]

This method sets the margin for the recovery of off-plane ionization charge. See RecoverOffPlaneDeposit() for a description of that feature.

This method is used by LArVoxelReadout::Setup().

Definition at line 272 of file LArVoxelReadout.h.

273  {
274  fOffPlaneMargin = std::max(margin, 0.0);
275  }
double fOffPlaneMargin
Charge deposited within this many [cm] from the plane is lead onto it.
void larg4::LArVoxelReadout::SetPropertiesData ( detinfo::DetectorPropertiesData const *const  detProp)
inlineprivatenoexcept

Definition at line 257 of file LArVoxelReadout.h.

258  {
259  fDetProp = detProp;
260  }
detinfo::DetectorPropertiesData const * fDetProp
auto const detProp
void larg4::LArVoxelReadout::SetRandomEngines ( CLHEP::HepRandomEngine *  pPropGen)
private

Sets the random generators to be used.

Definition at line 295 of file LArVoxelReadout.cxx.

296  {
297  assert(pPropGen); // random engine must be present
298  fPropGen = pPropGen;
299  }
CLHEP::HepRandomEngine * fPropGen
random engine for charge propagation
void larg4::LArVoxelReadout::SetSingleTPC ( unsigned int  cryostat,
unsigned int  tpc 
)

Associates this readout to one specific TPC.

Definition at line 83 of file LArVoxelReadout.cxx.

84  {
85  bSingleTPC = true;
86  fCstat = cryostat;
87  fTPC = tpc;
88  MF_LOG_DEBUG("LArVoxelReadout") << GetName() << "covers C=" << fCstat << " T=" << fTPC;
89  }
unsigned int fTPC
which TPC this LArVoxelReadout corresponds to
bool bSingleTPC
true if this readout is associated with a single TPC
unsigned int fCstat
and in which cryostat (if bSingleTPC is true)
void larg4::LArVoxelReadout::Setup ( Setup_t const &  setupData)

Reads all the configuration elements from setupData

Definition at line 75 of file LArVoxelReadout.cxx.

76  {
77  SetOffPlaneChargeRecoveryMargin(setupData.offPlaneMargin);
78  SetRandomEngines(setupData.propGen);
79  }
void SetRandomEngines(CLHEP::HepRandomEngine *pPropGen)
Sets the random generators to be used.
void SetOffPlaneChargeRecoveryMargin(double margin)
Sets the margin for recovery of charge drifted off-plane.

Friends And Related Function Documentation

friend class LArVoxelReadoutGeometry
friend

Definition at line 248 of file LArVoxelReadout.h.

Member Data Documentation

bool larg4::LArVoxelReadout::bSingleTPC
private

true if this readout is associated with a single TPC

Definition at line 356 of file LArVoxelReadout.h.

std::vector<std::vector<ChannelMap_t> > larg4::LArVoxelReadout::fChannelMaps
private

Maps of cryostat, tpc to channel data.

Definition at line 350 of file LArVoxelReadout.h.

detinfo::DetectorClocksData const* larg4::LArVoxelReadout::fClockData {nullptr}
private

Definition at line 360 of file LArVoxelReadout.h.

unsigned int larg4::LArVoxelReadout::fCstat
private

and in which cryostat (if bSingleTPC is true)

Definition at line 355 of file LArVoxelReadout.h.

detinfo::DetectorPropertiesData const* larg4::LArVoxelReadout::fDetProp {nullptr}
private

Definition at line 361 of file LArVoxelReadout.h.

bool larg4::LArVoxelReadout::fDontDriftThem
private

Definition at line 345 of file LArVoxelReadout.h.

double larg4::LArVoxelReadout::fDriftVelocity[3]
private

Definition at line 339 of file LArVoxelReadout.h.

double larg4::LArVoxelReadout::fElectronClusterSize
private

Definition at line 343 of file LArVoxelReadout.h.

double larg4::LArVoxelReadout::fElectronLifetime
private

Definition at line 342 of file LArVoxelReadout.h.

art::ServiceHandle<geo::Geometry const> larg4::LArVoxelReadout::fGeoHandle
private

Handle to the Geometry service.

Definition at line 351 of file LArVoxelReadout.h.

art::ServiceHandle<sim::LArG4Parameters const> larg4::LArVoxelReadout::fLgpHandle
private

Handle to the LArG4 parameters service.

Definition at line 353 of file LArVoxelReadout.h.

double larg4::LArVoxelReadout::fLongitudinalDiffusion
private

Definition at line 340 of file LArVoxelReadout.h.

int larg4::LArVoxelReadout::fMinNumberOfElCluster
private

Definition at line 344 of file LArVoxelReadout.h.

size_t larg4::LArVoxelReadout::fNSteps
private

Definition at line 368 of file LArVoxelReadout.h.

double larg4::LArVoxelReadout::fOffPlaneMargin = 0.0
private

Charge deposited within this many [cm] from the plane is lead onto it.

Definition at line 348 of file LArVoxelReadout.h.

CLHEP::HepRandomEngine* larg4::LArVoxelReadout::fPropGen = nullptr
private

random engine for charge propagation

Definition at line 358 of file LArVoxelReadout.h.

std::vector<unsigned short int> larg4::LArVoxelReadout::fSkipWireSignalInTPCs
private

Definition at line 346 of file LArVoxelReadout.h.

G4ThreeVector larg4::LArVoxelReadout::fStepEnd
private

Definition at line 367 of file LArVoxelReadout.h.

G4ThreeVector larg4::LArVoxelReadout::fStepStart
private

Definition at line 366 of file LArVoxelReadout.h.

unsigned int larg4::LArVoxelReadout::fTPC
private

which TPC this LArVoxelReadout corresponds to

Definition at line 354 of file LArVoxelReadout.h.

double larg4::LArVoxelReadout::fTransverseDiffusion
private

Definition at line 341 of file LArVoxelReadout.h.


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