LArSoft  v06_85_00
Liquid Argon Software toolkit - http://larsoft.org/
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::SimChannelChannelMap_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...
 
virtual ~LArVoxelReadout ()
 
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 ()
 Returns the accumulated channel -> SimChannel map for the single TPC. More...
 
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)
 Returns the accumulated channel -> SimChannel map for the specified TPC. More...
 

Private Member Functions

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 (G4ThreeVector stepMidPoint, const double simTime, int trackID, unsigned short int cryostat, unsigned short int tpc)
 
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::GeometryfGeoHandle
 Handle to the Geometry service. More...
 
art::ServiceHandle< sim::LArG4ParametersfLgpHandle
 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::ElecClock fClock
 TPC electronics clock. More...
 
G4ThreeVector fStepStart
 
G4ThreeVector fStepEnd
 
size_t fNSteps
 

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:

  • lead off-plane charge to the planes: regulated by RecoverOffPlaneDeposit(), if charge which reaches a wire plane is actually off it by less than the chosen margin, it's accounted for by that plane; by default the margin is 0 and all the charge off the plane is lost (with a warning)

Definition at line 157 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 161 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 47 of file LArVoxelReadout.cxx.

References ClearSimChannels(), fClock, SetDiscoverTPC(), SetSingleTPC(), and detinfo::DetectorClocks::TPCClock().

48  : G4VSensitiveDetector(name)
49  {
50  // Initialize values for the electron-cluster calculation.
52 
53  const detinfo::DetectorClocks* ts = lar::providerFrom<detinfo::DetectorClocksService>();
54  fClock = ts->TPCClock();
55 
56  // the standard name contains cryostat and TPC;
57  // if we don't find it, we will detect the TPC at each Geant hit
58  unsigned int cryostat, tpc;
59  if (std::sscanf(name.c_str(),"%*19s%1u%*4s%u",&cryostat, &tpc) == 2)
60  SetSingleTPC(cryostat, tpc);
61  else
63 
64  } // LArVoxelReadout::LArVoxelReadout()
virtual const ::detinfo::ElecClock & TPCClock() const =0
Lends a constant TPC clock with time set to trigger time.
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.
Conversion of times between different formats and references.
::detinfo::ElecClock fClock
TPC electronics clock.
larg4::LArVoxelReadout::LArVoxelReadout ( std::string const &  name,
unsigned int  cryostat,
unsigned int  tpc 
)

Constructor. Sets which TPC to work on.

Definition at line 70 of file LArVoxelReadout.cxx.

References SetSingleTPC().

71  : LArVoxelReadout(name)
72  { SetSingleTPC(cryostat, tpc); }
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.
larg4::LArVoxelReadout::~LArVoxelReadout ( )
virtual

Definition at line 102 of file LArVoxelReadout.cxx.

102 {}

Member Function Documentation

void larg4::LArVoxelReadout::clear ( void  )
virtual

Definition at line 142 of file LArVoxelReadout.cxx.

143  {
144  }
void larg4::LArVoxelReadout::ClearSimChannels ( )

Definition at line 147 of file LArVoxelReadout.cxx.

References fChannelMaps, fGeoHandle, geo::GeometryCore::Ncryostats(), and geo::GeometryCore::NTPC().

Referenced by LArVoxelReadout().

147  {
149  size_t cryo = 0;
150  for (auto& cryoData: fChannelMaps) { // each, a vector of maps
151  cryoData.resize(fGeoHandle->NTPC(cryo++));
152  for (auto& channelsMap: cryoData) channelsMap.clear(); // each, a map
153  } // for cryostats
154  } // LArVoxelReadout::ClearSimChannels()
art::ServiceHandle< geo::Geometry > fGeoHandle
Handle to the Geometry service.
unsigned int Ncryostats() const
Returns the number of cryostats in the detector.
std::vector< std::vector< ChannelMap_t > > fChannelMaps
Maps of cryostat, tpc to channel data.
unsigned int NTPC(unsigned int cstat=0) const
Returns the total number of TPCs in the specified cryostat.
void larg4::LArVoxelReadout::DrawAll ( )
virtual

Definition at line 582 of file LArVoxelReadout.cxx.

582 {}
void larg4::LArVoxelReadout::DriftIonizationElectrons ( G4ThreeVector  stepMidPoint,
const double  simTime,
int  trackID,
unsigned short int  cryostat,
unsigned short int  tpc 
)
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 331 of file LArVoxelReadout.cxx.

References sim::SimChannel::AddIonizationElectrons(), geo::TPCGeo::DriftDirection(), e, energy, larg4::IonizationAndScintillation::EnergyDeposit(), fChannelMaps, fClock, fDriftVelocity, fElectronClusterSize, fElectronLifetime, fGeoHandle, fLongitudinalDiffusion, fMinNumberOfElCluster, fOffPlaneMargin, fPropGen, fTransverseDiffusion, larg4::IonizationAndScintillation::Instance(), geo::kNegX, geo::kPosX, LOG_DEBUG, geo::GeometryCore::NearestChannel(), geo::TPCGeo::Nplanes(), larg4::IonizationAndScintillation::NumberIonizationElectrons(), geo::TPCGeo::Plane(), geo::TPCGeo::Plane0Pitch(), geo::TPCGeo::PlaneLocation(), geo::TPCGeo::PlanePitch(), RecoverOffPlaneDeposit(), detinfo::ElecClock::Ticks(), geo::GeometryCore::TPC(), and xx.

Referenced by ProcessHits().

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

Definition at line 135 of file LArVoxelReadout.cxx.

References fNSteps.

136  {
137  mf::LogWarning("LArVoxelReadout") << "Total number of steps was " << fNSteps << std::endl;
138 
139  } // LArVoxelReadout::EndOfEvent()
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
const LArVoxelReadout::ChannelMap_t & larg4::LArVoxelReadout::GetSimChannelMap ( ) const

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

Definition at line 157 of file LArVoxelReadout.cxx.

References bSingleTPC, fCstat, and fTPC.

Referenced by GetSimChannelMap(), and larg4::LArG4::produce().

158  {
159  if (bSingleTPC) return GetSimChannelMap(fCstat, fTPC);
160  throw cet::exception("LArVoxelReadout") << "TPC not specified";
161  } // LArVoxelReadout::GetSimChannelMap() const
unsigned int fTPC
which TPC this LArVoxelReadout corresponds to
const ChannelMap_t & GetSimChannelMap() const
Returns the accumulated channel -> 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)
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
LArVoxelReadout::ChannelMap_t & larg4::LArVoxelReadout::GetSimChannelMap ( )

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

Definition at line 163 of file LArVoxelReadout.cxx.

References bSingleTPC, fCstat, fTPC, and GetSimChannelMap().

163  {
164  if (bSingleTPC) return GetSimChannelMap(fCstat, fTPC);
165  throw cet::exception("LArVoxelReadout") << "TPC not specified";
166  } // LArVoxelReadout::GetSimChannelMap()
unsigned int fTPC
which TPC this LArVoxelReadout corresponds to
const ChannelMap_t & GetSimChannelMap() const
Returns the accumulated channel -> 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)
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
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 170 of file LArVoxelReadout.cxx.

References fChannelMaps, and GetSimChannelMap().

171  { return fChannelMaps.at(cryo).at(tpc); }
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 
)

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

Definition at line 174 of file LArVoxelReadout.cxx.

References fChannelMaps.

175  { return fChannelMaps.at(cryo).at(tpc); }
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 178 of file LArVoxelReadout.cxx.

References bSingleTPC, fCstat, and fTPC.

178  {
179  if (bSingleTPC) return GetSimChannels(fCstat, fTPC);
180  throw cet::exception("LArVoxelReadout") << "TPC not specified";
181  } // LArVoxelReadout::GetSimChannels()
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)
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
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 184 of file LArVoxelReadout.cxx.

References fChannelMaps.

185  {
186  std::vector<sim::SimChannel> channels;
187  const ChannelMap_t& chmap = fChannelMaps.at(cryo).at(tpc);
188  channels.reserve(chmap.size());
189  for(const auto& chpair: chmap) channels.push_back(chpair.second);
190  return channels;
191  } // LArVoxelReadout::GetSimChannels(short, short)
std::map< unsigned int, sim::SimChannel > ChannelMap_t
Type of map channel -> 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 304 of file LArVoxelReadout.h.

Referenced by ProcessHits().

305  {
306  for (auto c: v) if (c == tpc) return true;
307  return false;
308  }
void larg4::LArVoxelReadout::Initialize ( G4HCofThisEvent )
virtual

Definition at line 106 of file LArVoxelReadout.cxx.

References sim::LArG4Parameters::DisableWireplanes(), sim::LArG4Parameters::ElectronClusterSize(), fDontDriftThem, fDriftVelocity, fElectronClusterSize, fElectronLifetime, fLgpHandle, fLongitudinalDiffusion, fMinNumberOfElCluster, fNSteps, fSkipWireSignalInTPCs, fTransverseDiffusion, LOG_DEBUG, sim::LArG4Parameters::LongitudinalDiffusion(), sim::LArG4Parameters::MinNumberOfElCluster(), sim::LArG4Parameters::NoElectronPropagation(), sim::LArG4Parameters::SkipWireSignalInTPCs(), and sim::LArG4Parameters::TransverseDiffusion().

107  {
108  // for c2: larp is unused
109  //auto const * larp = lar::providerFrom<detinfo::LArPropertiesService>();
110  auto const * detprop = lar::providerFrom<detinfo::DetectorPropertiesService>();
111  fElectronLifetime = detprop->ElectronLifetime();
112  for (int i = 0; i<3; ++i)
113  fDriftVelocity[i] = detprop->DriftVelocity(detprop->Efield(i),
114  detprop->Temperature())/1000.;
115 
122 
123  LOG_DEBUG("LArVoxelReadout") << " e lifetime: " << fElectronLifetime
124  << "\n Temperature: " << detprop->Temperature()
125  << "\n Drift velocity: " << fDriftVelocity[0]
126  <<" "<<fDriftVelocity[1]<<" "<<fDriftVelocity[2];
127 
129 
130  fNSteps=0;
131  }
art::ServiceHandle< sim::LArG4Parameters > fLgpHandle
Handle to the LArG4 parameters service.
double TransverseDiffusion() const
bool NoElectronPropagation() const
std::vector< unsigned short int > fSkipWireSignalInTPCs
double ElectronClusterSize() const
const std::vector< unsigned short int > SkipWireSignalInTPCs() const
int MinNumberOfElCluster() const
#define LOG_DEBUG(id)
double LongitudinalDiffusion() const
bool DisableWireplanes() const
void larg4::LArVoxelReadout::PrintAll ( )
virtual

Definition at line 583 of file LArVoxelReadout.cxx.

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

Definition at line 196 of file LArVoxelReadout.cxx.

References bSingleTPC, DriftIonizationElectrons(), fCstat, fDontDriftThem, fNSteps, fSkipWireSignalInTPCs, fTPC, larg4::ParticleListAction::GetCurrentTrackID(), Has(), larg4::G4PVPlacementWithID< IDTYPE >::ID, larg4::IonizationAndScintillation::Instance(), LOG_DEBUG, and larg4::IonizationAndScintillation::Reset().

197  {
198  // All work done for the "parallel world" "box of voxels" in
199  // LArVoxelReadoutGeometry makes this a fairly simple routine.
200  // First, the usual check for non-zero energy:
201 
202  // Only process the hit if the step is inside the active volume and
203  // it has deposited energy. The hit being inside the active volume
204  // is virtually sure to happen because the LArVoxelReadoutGeometry
205  // that this class makes use of only has voxels for inside the TPC.
206 
207  // The step can be no bigger than the size of the voxel,
208  // because of the geometry set up in LArVoxelGeometry and the
209  // transportation set up in PhysicsList. Find the mid-point
210  // of the step.
211 
212  if ( step->GetTotalEnergyDeposit() > 0 ){
213 
214  // Make sure we have the IonizationAndScintillation singleton
215  // reset to this step
217  fNSteps++;
218  if( !fDontDriftThem ){
219 
220  G4ThreeVector midPoint = 0.5*( step->GetPreStepPoint()->GetPosition()
221  + step->GetPostStepPoint()->GetPosition() );
222  double g4time = step->GetPreStepPoint()->GetGlobalTime();
223 
224  // Find the Geant4 track ID for the particle responsible for depositing the
225  // energy. if we are only storing primary EM shower particles, and this energy
226  // is from a secondary etc EM shower particle, the ID returned is the primary
227  const int trackID = ParticleListAction::GetCurrentTrackID();
228 
229  // Find out which TPC we are in.
230  // If this readout object covers just one, we already know it.
231  // Otherwise, we have to ask Geant where we are.
232  unsigned short int cryostat = 0, tpc = 0;
233  if (bSingleTPC) {
234  cryostat = fCstat;
235  tpc = fTPC;
236  }
237  else {
238  // detect the TPC we are in
239  const G4VTouchable* pTouchable = step->GetPreStepPoint()->GetTouchable();
240  if (!pTouchable) {
241  throw cet::exception
242  ("LArG4") << "Untouchable step in LArVoxelReadout::ProcessHits()";
243  }
244 
245  // one of the ancestors of the touched volume is supposed to be
246  // actually a G4PVPlacementInTPC that knows which TPC it covers;
247  // currently, it's the 4th in the ladder:
248  // [0] voxel [1] voxel tower [2] voxel plane [3] the full box;
249  G4int depth = 0;
250  while (depth < pTouchable->GetHistoryDepth()) {
251  const G4PVPlacementInTPC* pPVinTPC =
252  dynamic_cast<const G4PVPlacementInTPC*>
253  (pTouchable->GetVolume(depth++));
254  if (!pPVinTPC) continue;
255  cryostat = pPVinTPC->ID.Cryostat;
256  tpc = pPVinTPC->ID.TPC;
257  if (Has(fSkipWireSignalInTPCs, tpc))
258  {
259  return true;
260  }
261  break;
262  } // while
263  if (depth < pTouchable->GetHistoryDepth()) {
264  // this is a fundamental error where the step does not happen in
265  // any TPC; this should not happen in the readout geometry!
266  throw cet::exception
267  ("LArG4") << "No TPC ID found in LArVoxelReadout::ProcessHits()";
268  } // if
269  LOG_DEBUG("LArVoxelReadoutHit") << " hit in C=" << cryostat << " T=" << tpc;
270  } // if more than one TPC
271 
272  // Note that if there is no particle ID for this energy deposit, the
273  // trackID will be sim::NoParticleId.
274 
275  DriftIonizationElectrons(midPoint, g4time, trackID, cryostat, tpc);
276  } // end we are drifting
277  } // end there is non-zero energy deposition
278 
279  return true;
280  }
unsigned int fTPC
which TPC this LArVoxelReadout corresponds to
bool bSingleTPC
true if this readout is associated with a single TPC
std::vector< unsigned short int > fSkipWireSignalInTPCs
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
void DriftIonizationElectrons(G4ThreeVector stepMidPoint, const double simTime, int trackID, unsigned short int cryostat, unsigned short int tpc)
unsigned int fCstat
and in which cryostat (if bSingleTPC is true)
#define LOG_DEBUG(id)
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
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 292 of file LArVoxelReadout.cxx.

References geo::PlaneGeo::ComposePoint(), geo::PlaneGeo::DeltaFromActivePlane(), geo::PlaneGeo::DistanceFromPlane(), fOffPlaneMargin, and geo::PlaneGeo::PointWidthDepthProjection().

Referenced by DriftIonizationElectrons(), and SetRandomEngines().

293  {
294  //
295  // translate the landing position on the two frame coordinates
296  // ("width" and "depth")
297  //
298  auto const landingPos = plane.PointWidthDepthProjection(pos);
299 
300  //
301  // compute the distance of the landing position on the two frame
302  // coordinates ("width" and "depth");
303  // keep the point within 10 micrometers (0.001 cm) from the border
304  //
305  auto const offPlane = plane.DeltaFromActivePlane(landingPos, 0.001);
306 
307  //
308  // if both the distances are below the margin, move the point to
309  // the border
310  //
311 
312  // nothing to recover: landing is inside
313  if ((offPlane.X() == 0.0) && (offPlane.Y() == 0.0)) return pos;
314 
315  // won't recover: too far
316  if ((std::abs(offPlane.X()) > fOffPlaneMargin)
317  || (std::abs(offPlane.Y()) > fOffPlaneMargin))
318  return pos;
319 
320  // we didn't fully decompose because it might be unnecessary;
321  // now we need the full thing
322  auto const distance = plane.DistanceFromPlane(pos);
323 
324  return plane.ComposePoint<geo::Point_t>(distance, landingPos + offPlane);
325 
326  } // LArVoxelReadout::RecoverOffPlaneDeposit()
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:187
void larg4::LArVoxelReadout::SetDiscoverTPC ( )

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

Definition at line 93 of file LArVoxelReadout.cxx.

References bSingleTPC, fCstat, fTPC, and LOG_DEBUG.

Referenced by LArVoxelReadout().

93  {
94  bSingleTPC = false;
95  fCstat = 0;
96  fTPC = 0;
97  LOG_DEBUG("LArVoxelReadout") << GetName() << " autodetects TPC";
98  } // LArVoxelReadout::SetDiscoverTPC()
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)
#define LOG_DEBUG(id)
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 251 of file LArVoxelReadout.h.

References max.

Referenced by Setup().

252  { fOffPlaneMargin = std::max(margin, 0.0); }
Int_t max
Definition: plot.C:27
double fOffPlaneMargin
Charge deposited within this many [cm] from the plane is lead onto it.
void larg4::LArVoxelReadout::SetRandomEngines ( CLHEP::HepRandomEngine *  pPropGen)
private

Sets the random generators to be used.

Definition at line 284 of file LArVoxelReadout.cxx.

References fPropGen, and RecoverOffPlaneDeposit().

Referenced by Setup().

284  {
285  assert(pPropGen); // random engine must be present
286  fPropGen = pPropGen;
287  } // LArVoxelReadout::SetRandomEngines()
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 85 of file LArVoxelReadout.cxx.

References bSingleTPC, fCstat, fTPC, and LOG_DEBUG.

Referenced by larg4::LArVoxelReadoutGeometry::Construct(), and LArVoxelReadout().

85  {
86  bSingleTPC = true;
87  fCstat = cryostat;
88  fTPC = tpc;
89  LOG_DEBUG("LArVoxelReadout")
90  << GetName() << "covers C=" << fCstat << " T=" << fTPC;
91  } // LArVoxelReadout::SetSingleTPC()
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)
#define LOG_DEBUG(id)
void larg4::LArVoxelReadout::Setup ( Setup_t const &  setupData)

Reads all the configuration elements from setupData

Definition at line 76 of file LArVoxelReadout.cxx.

References larg4::LArVoxelReadout::Setup_t::offPlaneMargin, larg4::LArVoxelReadout::Setup_t::propGen, SetOffPlaneChargeRecoveryMargin(), and SetRandomEngines().

Referenced by larg4::LArVoxelReadoutGeometry::Construct().

76  {
77 
78  SetOffPlaneChargeRecoveryMargin(setupData.offPlaneMargin);
79  SetRandomEngines(setupData.propGen);
80 
81  } // LArVoxelReadout::Setup()
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.

Member Data Documentation

bool larg4::LArVoxelReadout::bSingleTPC
private

true if this readout is associated with a single TPC

Definition at line 332 of file LArVoxelReadout.h.

Referenced by GetSimChannelMap(), GetSimChannels(), ProcessHits(), SetDiscoverTPC(), and SetSingleTPC().

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

Maps of cryostat, tpc to channel data.

Definition at line 327 of file LArVoxelReadout.h.

Referenced by ClearSimChannels(), DriftIonizationElectrons(), GetSimChannelMap(), and GetSimChannels().

::detinfo::ElecClock larg4::LArVoxelReadout::fClock
private

TPC electronics clock.

Definition at line 336 of file LArVoxelReadout.h.

Referenced by DriftIonizationElectrons(), and LArVoxelReadout().

unsigned int larg4::LArVoxelReadout::fCstat
private

and in which cryostat (if bSingleTPC is true)

Definition at line 331 of file LArVoxelReadout.h.

Referenced by GetSimChannelMap(), GetSimChannels(), ProcessHits(), SetDiscoverTPC(), and SetSingleTPC().

bool larg4::LArVoxelReadout::fDontDriftThem
private

Definition at line 322 of file LArVoxelReadout.h.

Referenced by Initialize(), and ProcessHits().

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

Definition at line 313 of file LArVoxelReadout.h.

Referenced by DriftIonizationElectrons(), and Initialize().

double larg4::LArVoxelReadout::fElectronClusterSize
private

Definition at line 317 of file LArVoxelReadout.h.

Referenced by DriftIonizationElectrons(), and Initialize().

double larg4::LArVoxelReadout::fElectronLifetime
private

Definition at line 316 of file LArVoxelReadout.h.

Referenced by DriftIonizationElectrons(), and Initialize().

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

Handle to the Geometry service.

Definition at line 328 of file LArVoxelReadout.h.

Referenced by ClearSimChannels(), and DriftIonizationElectrons().

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

Handle to the LArG4 parameters service.

Definition at line 329 of file LArVoxelReadout.h.

Referenced by Initialize().

double larg4::LArVoxelReadout::fLongitudinalDiffusion
private

Definition at line 314 of file LArVoxelReadout.h.

Referenced by DriftIonizationElectrons(), and Initialize().

int larg4::LArVoxelReadout::fMinNumberOfElCluster
private

Definition at line 318 of file LArVoxelReadout.h.

Referenced by DriftIonizationElectrons(), and Initialize().

size_t larg4::LArVoxelReadout::fNSteps
private

Definition at line 343 of file LArVoxelReadout.h.

Referenced by EndOfEvent(), Initialize(), and ProcessHits().

double larg4::LArVoxelReadout::fOffPlaneMargin = 0.0
private

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

Definition at line 325 of file LArVoxelReadout.h.

Referenced by DriftIonizationElectrons(), and RecoverOffPlaneDeposit().

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

random engine for charge propagation

Definition at line 334 of file LArVoxelReadout.h.

Referenced by DriftIonizationElectrons(), and SetRandomEngines().

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

Definition at line 323 of file LArVoxelReadout.h.

Referenced by Initialize(), and ProcessHits().

G4ThreeVector larg4::LArVoxelReadout::fStepEnd
private

Definition at line 342 of file LArVoxelReadout.h.

G4ThreeVector larg4::LArVoxelReadout::fStepStart
private

Definition at line 341 of file LArVoxelReadout.h.

unsigned int larg4::LArVoxelReadout::fTPC
private

which TPC this LArVoxelReadout corresponds to

Definition at line 330 of file LArVoxelReadout.h.

Referenced by GetSimChannelMap(), GetSimChannels(), ProcessHits(), SetDiscoverTPC(), and SetSingleTPC().

double larg4::LArVoxelReadout::fTransverseDiffusion
private

Definition at line 315 of file LArVoxelReadout.h.

Referenced by DriftIonizationElectrons(), and Initialize().


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