LArSoft  v06_85_00
Liquid Argon Software toolkit - http://larsoft.org/
detsim::SimDriftElectrons Class Reference
Inheritance diagram for detsim::SimDriftElectrons:
art::EDProducer art::ProducerBase art::Consumer art::EngineCreator art::ProductRegistryHelper

Classes

struct  ChannelBookKeeping_t
 

Public Types

using ModuleType = EDProducer
 
using WorkerType = WorkerT< EDProducer >
 
template<typename UserConfig , typename KeysToIgnore = void>
using Table = ProducerBase::Table< UserConfig, KeysToIgnore >
 

Public Member Functions

 SimDriftElectrons (fhicl::ParameterSet const &pset)
 
virtual ~SimDriftElectrons ()
 
void produce (art::Event &evt)
 
void beginJob ()
 
void endJob ()
 
void reconfigure (fhicl::ParameterSet const &p)
 
template<typename PROD , BranchType B = InEvent>
ProductID getProductID (std::string const &instanceName={}) const
 
template<typename PROD , BranchType B>
ProductID getProductID (ModuleDescription const &moduleDescription, std::string const &instanceName) const
 
bool modifiesEvent () const
 
template<typename T , BranchType = InEvent>
ProductToken< T > consumes (InputTag const &)
 
template<typename T , art::BranchType BT>
art::ProductToken< T > consumes (InputTag const &it)
 
template<typename T , BranchType = InEvent>
void consumesMany ()
 
template<typename Element , BranchType = InEvent>
ViewToken< Element > consumesView (InputTag const &)
 
template<typename T , art::BranchType BT>
art::ViewToken< T > consumesView (InputTag const &it)
 
template<typename T , BranchType = InEvent>
ProductToken< T > mayConsume (InputTag const &)
 
template<typename T , art::BranchType BT>
art::ProductToken< T > mayConsume (InputTag const &it)
 
template<typename T , BranchType = InEvent>
void mayConsumeMany ()
 
template<typename Element , BranchType = InEvent>
ViewToken< Element > mayConsumeView (InputTag const &)
 
template<typename T , art::BranchType BT>
art::ViewToken< T > mayConsumeView (InputTag const &it)
 
base_engine_tcreateEngine (seed_t seed)
 
base_engine_tcreateEngine (seed_t seed, std::string const &kind_of_engine_to_make)
 
base_engine_tcreateEngine (seed_t seed, std::string const &kind_of_engine_to_make, label_t const &engine_label)
 
seed_t get_seed_value (fhicl::ParameterSet const &pset, char const key[]="seed", seed_t const implicit_seed=-1)
 

Static Public Member Functions

static cet::exempt_ptr< Consumernon_module_context ()
 

Protected Member Functions

CurrentProcessingContext const * currentContext () const
 
void validateConsumedProduct (BranchType const bt, ProductInfo const &pi)
 
void prepareForJob (fhicl::ParameterSet const &pset)
 
void showMissingConsumes () const
 

Private Types

typedef std::map< raw::ChannelID_t, ChannelBookKeeping_tChannelMap_t
 

Private Attributes

art::InputTag fSimModuleLabel
 
const detinfo::DetectorClocksfTimeService
 
std::unique_ptr< CLHEP::RandGauss > fRandGauss
 
double fElectronLifetime
 
double fElectronClusterSize
 
int fMinNumberOfElCluster
 
double fLongitudinalDiffusion
 
double fTransverseDiffusion
 
double fLifetimeCorr_const
 
double fLDiff_const
 
double fTDiff_const
 
double fRecipDriftVel [3]
 
bool fStoreDriftedElectronClusters
 
std::vector< std::vector< ChannelMap_t > > fChannelMaps
 
size_t fNCryostats
 
std::vector< size_t > fNTPCs
 
std::vector< double > fXDiff
 
std::vector< double > fYDiff
 
std::vector< double > fZDiff
 
std::vector< double > fnElDiff
 
std::vector< double > fnEnDiff
 
double fDriftClusterPos [3]
 
art::ServiceHandle< geo::GeometryfGeometry
 Handle to the Geometry service. More...
 
::detinfo::ElecClock fClock
 TPC electronics clock. More...
 
larg4::ISCalculationSeparate fISAlg
 

Detailed Description

Definition at line 95 of file SimDriftElectrons_module.cc.

Member Typedef Documentation

using art::EDProducer::ModuleType = EDProducer
inherited

Definition at line 34 of file EDProducer.h.

template<typename UserConfig , typename KeysToIgnore = void>
using art::EDProducer::Table = ProducerBase::Table<UserConfig, KeysToIgnore>
inherited

Definition at line 43 of file EDProducer.h.

using art::EDProducer::WorkerType = WorkerT<EDProducer>
inherited

Definition at line 35 of file EDProducer.h.

Constructor & Destructor Documentation

detsim::SimDriftElectrons::SimDriftElectrons ( fhicl::ParameterSet const &  pset)
explicit

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.

Definition at line 179 of file SimDriftElectrons_module.cc.

References art::EngineCreator::createEngine(), fStoreDriftedElectronClusters, and reconfigure().

180  {
181  this->reconfigure(pset);
182 
183  produces< std::vector<sim::SimChannel> >();
184  if(fStoreDriftedElectronClusters)produces< std::vector<sim::SimDriftedElectronCluster> >();
185  //produces< art::Assns<sim::SimChannel, sim::SimEnergyDeposit> >();
186 
187  // create a default random engine; obtain the random seed from
188  // NuRandomService, unless overridden in configuration with key
189  // "Seed"
191  ->createEngine(*this, pset, "Seed");
192 
201  //fOffPlaneMargin = pset.get< double >("ChargeRecoveryMargin",0.0);
202  // Protection against a silly value.
203  //fOffPlaneMargin = std::max(fOffPlaneMargin,0.0);
204  }
base_engine_t & createEngine(seed_t seed)
void reconfigure(fhicl::ParameterSet const &p)
virtual detsim::SimDriftElectrons::~SimDriftElectrons ( )
inlinevirtual

Definition at line 100 of file SimDriftElectrons_module.cc.

References beginJob(), endJob(), produce(), and reconfigure().

100 {};

Member Function Documentation

void detsim::SimDriftElectrons::beginJob ( )
virtual

Reimplemented from art::EDProducer.

Definition at line 219 of file SimDriftElectrons_module.cc.

References e, sim::LArG4Parameters::ElectronClusterSize(), fClock, fElectronClusterSize, fElectronLifetime, fGeometry, fISAlg, fLDiff_const, fLifetimeCorr_const, fLongitudinalDiffusion, fMinNumberOfElCluster, fNCryostats, fNTPCs, fRandGauss, fRecipDriftVel, fTDiff_const, fTimeService, fTransverseDiffusion, art::RandomNumberGenerator::getEngine(), larg4::ISCalculationSeparate::Initialize(), LOG_DEBUG, sim::LArG4Parameters::LongitudinalDiffusion(), sim::LArG4Parameters::MinNumberOfElCluster(), n, geo::GeometryCore::Ncryostats(), geo::GeometryCore::NTPC(), art::EngineCreator::rng(), detinfo::DetectorClocks::TPCClock(), and sim::LArG4Parameters::TransverseDiffusion().

Referenced by ~SimDriftElectrons().

220  {
221  fTimeService = lar::providerFrom<detinfo::DetectorClocksService>();
223 
224  // Set up the gaussian generator.
226  CLHEP::HepRandomEngine& engine = rng->getEngine();
227  fRandGauss = std::unique_ptr<CLHEP::RandGauss>(new CLHEP::RandGauss(engine));
228 
229  // Define the physical constants we'll use.
230 
231  auto const * detprop = lar::providerFrom<detinfo::DetectorPropertiesService>();
232  fElectronLifetime = detprop->ElectronLifetime(); // Electron lifetime as returned by the DetectorProperties service assumed to be in us;
233  for (int i = 0; i<3; ++i) {
234  double driftVelocity = detprop->DriftVelocity(detprop->Efield(i),
235  detprop->Temperature())*1.e-3; // Drift velocity as returned by the DetectorProperties service assumed to be in cm/us. Multiply by 1.e-3 to convert into LArSoft standard velocity units, cm/ns;
236 
237  fRecipDriftVel[i] = 1./driftVelocity;
238  }
239 
240  // To-do: Move the parameters we fetch from "LArG4" to detector
241  // properties.
243  fElectronClusterSize = paramHandle->ElectronClusterSize();
245  fLongitudinalDiffusion = paramHandle->LongitudinalDiffusion(); // cm^2/ns units
246  fTransverseDiffusion = paramHandle->TransverseDiffusion(); // cm^2/ns units
247 
248  LOG_DEBUG("SimDriftElectrons") << " e lifetime (ns): " << fElectronLifetime
249  << "\n Temperature (K): " << detprop->Temperature()
250  << "\n Drift velocity (cm/ns): " << 1./fRecipDriftVel[0]
251  <<" "<<1./fRecipDriftVel[1]<<" "<<1./fRecipDriftVel[2];
252 
253  // Opposite of lifetime. Convert from us to standard LArSoft time units, ns;
255  fLDiff_const = std::sqrt(2.*fLongitudinalDiffusion);
256  fTDiff_const = std::sqrt(2.*fTransverseDiffusion);
257 
258  // For this detector's geometry, save the number of cryostats and
259  // the number of TPCs within each cryostat.
261  fNTPCs.resize(fNCryostats);
262  for ( size_t n = 0; n < fNCryostats; ++n )
263  fNTPCs[n] = fGeometry->NTPC(n);
264 
265 
266  fISAlg.Initialize(lar::providerFrom<detinfo::LArPropertiesService>(),
267  detprop,
268  &(*paramHandle),
269  lar::providerFrom<spacecharge::SpaceChargeService>());
270 
271 
272  return;
273  }
virtual const ::detinfo::ElecClock & TPCClock() const =0
Lends a constant TPC clock with time set to trigger time.
larg4::ISCalculationSeparate fISAlg
art::ServiceHandle< geo::Geometry > fGeometry
Handle to the Geometry service.
unsigned int Ncryostats() const
Returns the number of cryostats in the detector.
base_engine_t & getEngine() const
double TransverseDiffusion() const
double ElectronClusterSize() const
const detinfo::DetectorClocks * fTimeService
unsigned int NTPC(unsigned int cstat=0) const
Returns the total number of TPCs in the specified cryostat.
static art::ServiceHandle< art::RandomNumberGenerator > & rng()
int MinNumberOfElCluster() const
::detinfo::ElecClock fClock
TPC electronics clock.
#define LOG_DEBUG(id)
Char_t n[5]
std::unique_ptr< CLHEP::RandGauss > fRandGauss
double LongitudinalDiffusion() const
Float_t e
Definition: plot.C:34
void Initialize(const detinfo::LArProperties *larp, const detinfo::DetectorProperties *detp, const sim::LArG4Parameters *lgp, const spacecharge::SpaceCharge *sce)
template<typename T , BranchType = InEvent>
ProductToken<T> art::Consumer::consumes ( InputTag const &  )
inherited
template<typename T , art::BranchType BT>
art::ProductToken<T> art::Consumer::consumes ( InputTag const &  it)
inherited

Definition at line 147 of file Consumer.h.

References art::InputTag::instance(), art::InputTag::label(), and art::InputTag::process().

148 {
149  if (!moduleContext_)
150  return ProductToken<T>::invalid();
151 
152  consumables_[BT].emplace_back(ConsumableType::Product,
153  TypeID{typeid(T)},
154  it.label(),
155  it.instance(),
156  it.process());
157  return ProductToken<T>{it};
158 }
static ProductToken< T > invalid()
Definition: ProductToken.h:47
ConsumableProducts consumables_
Definition: Consumer.h:138
bool moduleContext_
Definition: Consumer.h:136
template<typename T , art::BranchType BT>
void art::Consumer::consumesMany ( )
inherited

Definition at line 162 of file Consumer.h.

163 {
164  if (!moduleContext_)
165  return;
166 
167  consumables_[BT].emplace_back(ConsumableType::Many, TypeID{typeid(T)});
168 }
ConsumableProducts consumables_
Definition: Consumer.h:138
bool moduleContext_
Definition: Consumer.h:136
template<typename Element , BranchType = InEvent>
ViewToken<Element> art::Consumer::consumesView ( InputTag const &  )
inherited
template<typename T , art::BranchType BT>
art::ViewToken<T> art::Consumer::consumesView ( InputTag const &  it)
inherited

Definition at line 172 of file Consumer.h.

References art::InputTag::instance(), art::InputTag::label(), and art::InputTag::process().

173 {
174  if (!moduleContext_)
175  return ViewToken<T>::invalid();
176 
177  consumables_[BT].emplace_back(ConsumableType::ViewElement,
178  TypeID{typeid(T)},
179  it.label(),
180  it.instance(),
181  it.process());
182  return ViewToken<T>{it};
183 }
static ViewToken< Element > invalid()
Definition: ProductToken.h:75
ConsumableProducts consumables_
Definition: Consumer.h:138
bool moduleContext_
Definition: Consumer.h:136
EngineCreator::base_engine_t & EngineCreator::createEngine ( seed_t  seed,
std::string const &  kind_of_engine_to_make 
)
inherited

Definition at line 32 of file EngineCreator.cc.

References art::EngineCreator::rng().

34 {
35  return rng()->createEngine(
36  placeholder_schedule_id(), seed, kind_of_engine_to_make);
37 }
long seed
Definition: chem4.cc:68
static art::ServiceHandle< art::RandomNumberGenerator > & rng()
EngineCreator::base_engine_t & EngineCreator::createEngine ( seed_t  seed,
std::string const &  kind_of_engine_to_make,
label_t const &  engine_label 
)
inherited

Definition at line 40 of file EngineCreator.cc.

References art::EngineCreator::rng().

43 {
44  return rng()->createEngine(
45  placeholder_schedule_id(), seed, kind_of_engine_to_make, engine_label);
46 }
long seed
Definition: chem4.cc:68
static art::ServiceHandle< art::RandomNumberGenerator > & rng()
CurrentProcessingContext const * art::EDProducer::currentContext ( ) const
protectedinherited

Definition at line 120 of file EDProducer.cc.

References art::EDProducer::current_context_.

121  {
122  return current_context_.get();
123  }
CPC_exempt_ptr current_context_
Definition: EDProducer.h:116
void detsim::SimDriftElectrons::endJob ( )
virtual

Reimplemented from art::EDProducer.

Definition at line 276 of file SimDriftElectrons_module.cc.

Referenced by ~SimDriftElectrons().

277  {
278  }
EngineCreator::seed_t EngineCreator::get_seed_value ( fhicl::ParameterSet const &  pset,
char const  key[] = "seed",
seed_t const  implicit_seed = -1 
)
inherited

Definition at line 49 of file EngineCreator.cc.

References fhicl::ParameterSet::get().

Referenced by art::MixFilter< T >::initEngine_().

52 {
53  auto const& explicit_seeds = pset.get<std::vector<int>>(key, {});
54  return explicit_seeds.empty() ? implicit_seed : explicit_seeds.front();
55 }
template<typename PROD , BranchType B>
ProductID art::EDProducer::getProductID ( std::string const &  instanceName = {}) const
inlineinherited

Definition at line 123 of file EDProducer.h.

References art::EDProducer::moduleDescription_.

124  {
125  return ProducerBase::getProductID<PROD, B>(moduleDescription_,
126  instanceName);
127  }
ModuleDescription moduleDescription_
Definition: EDProducer.h:115
template<typename PROD , BranchType B>
ProductID art::ProducerBase::getProductID ( ModuleDescription const &  moduleDescription,
std::string const &  instanceName 
) const
inherited

Definition at line 56 of file ProducerBase.h.

References B, and art::ModuleDescription::moduleLabel().

Referenced by art::ProducerBase::modifiesEvent().

58  {
59  auto const& pd =
60  get_ProductDescription<PROD>(B, md.moduleLabel(), instanceName);
61  return pd.productID();
62  }
Int_t B
Definition: plot.C:25
template<typename T , BranchType = InEvent>
ProductToken<T> art::Consumer::mayConsume ( InputTag const &  )
inherited
template<typename T , art::BranchType BT>
art::ProductToken<T> art::Consumer::mayConsume ( InputTag const &  it)
inherited

Definition at line 190 of file Consumer.h.

References art::InputTag::instance(), art::InputTag::label(), and art::InputTag::process().

191 {
192  if (!moduleContext_)
193  return ProductToken<T>::invalid();
194 
195  consumables_[BT].emplace_back(ConsumableType::Product,
196  TypeID{typeid(T)},
197  it.label(),
198  it.instance(),
199  it.process());
200  return ProductToken<T>{it};
201 }
static ProductToken< T > invalid()
Definition: ProductToken.h:47
ConsumableProducts consumables_
Definition: Consumer.h:138
bool moduleContext_
Definition: Consumer.h:136
template<typename T , art::BranchType BT>
void art::Consumer::mayConsumeMany ( )
inherited

Definition at line 205 of file Consumer.h.

206 {
207  if (!moduleContext_)
208  return;
209 
210  consumables_[BT].emplace_back(ConsumableType::Many, TypeID{typeid(T)});
211 }
ConsumableProducts consumables_
Definition: Consumer.h:138
bool moduleContext_
Definition: Consumer.h:136
template<typename Element , BranchType = InEvent>
ViewToken<Element> art::Consumer::mayConsumeView ( InputTag const &  )
inherited
template<typename T , art::BranchType BT>
art::ViewToken<T> art::Consumer::mayConsumeView ( InputTag const &  it)
inherited

Definition at line 215 of file Consumer.h.

References art::InputTag::instance(), art::InputTag::label(), and art::InputTag::process().

216 {
217  if (!moduleContext_)
218  return ViewToken<T>::invalid();
219 
220  consumables_[BT].emplace_back(ConsumableType::ViewElement,
221  TypeID{typeid(T)},
222  it.label(),
223  it.instance(),
224  it.process());
225  return ViewToken<T>{it};
226 }
static ViewToken< Element > invalid()
Definition: ProductToken.h:75
ConsumableProducts consumables_
Definition: Consumer.h:138
bool moduleContext_
Definition: Consumer.h:136
bool art::ProducerBase::modifiesEvent ( ) const
inlineinherited

Definition at line 40 of file ProducerBase.h.

References art::ProducerBase::getProductID().

41  {
42  return true;
43  }
void art::Consumer::prepareForJob ( fhicl::ParameterSet const &  pset)
protectedinherited

Definition at line 89 of file Consumer.cc.

References fhicl::ParameterSet::get_if_present().

Referenced by art::EDProducer::doBeginJob(), art::EDFilter::doBeginJob(), and art::EDAnalyzer::doBeginJob().

90 {
91  if (!moduleContext_)
92  return;
93 
94  pset.get_if_present("errorOnMissingConsumes", requireConsumes_);
95  for (auto& consumablesPerBranch : consumables_) {
96  cet::sort_all(consumablesPerBranch);
97  }
98 }
bool requireConsumes_
Definition: Consumer.h:137
ConsumableProducts consumables_
Definition: Consumer.h:138
bool moduleContext_
Definition: Consumer.h:136
void detsim::SimDriftElectrons::produce ( art::Event evt)
virtual
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

Implements art::EDProducer.

Definition at line 281 of file SimDriftElectrons_module.cc.

References sim::SimChannel::AddIonizationElectrons(), larg4::ISCalculationSeparate::CalculateIonizationAndScintillation(), detsim::SimDriftElectrons::ChannelBookKeeping_t::channelIndex, DEFINE_ART_MODULE, geo::TPCGeo::DriftDirection(), e, energy, fChannelMaps, fClock, fDriftClusterPos, fElectronClusterSize, fGeometry, fISAlg, fLDiff_const, fLifetimeCorr_const, fMinNumberOfElCluster, fNCryostats, fnElDiff, fnEnDiff, fNTPCs, fRandGauss, fRecipDriftVel, fSimModuleLabel, fStoreDriftedElectronClusters, fTDiff_const, fTimeService, fXDiff, fYDiff, fZDiff, detinfo::DetectorClocks::G4ToElecTime(), art::DataViewImpl::getByLabel(), geo::kNegX, geo::kPosX, LOG_DEBUG, geo::GeometryCore::NearestChannel(), geo::TPCGeo::Nplanes(), larg4::ISCalculationSeparate::NumberIonizationElectrons(), geo::TPCGeo::Plane0Pitch(), geo::TPCGeo::PlaneLocation(), geo::TPCGeo::PlanePitch(), geo::GeometryCore::PositionToCryostat(), geo::GeometryCore::PositionToTPC(), larg4::ISCalculationSeparate::Reset(), detsim::SimDriftElectrons::ChannelBookKeeping_t::stepList, detinfo::ElecClock::Ticks(), geo::GeometryCore::TPC(), and xx.

Referenced by ~SimDriftElectrons().

282  {
283  // Fetch the SimEnergyDeposit objects for this event.
284  typedef art::Handle< std::vector<sim::SimEnergyDeposit> > energyDepositHandle_t;
285  energyDepositHandle_t energyDepositHandle;
286  // If there aren't any energy deposits for this event, don't
287  // panic. It's possible someone is doing a study with events
288  // outside the TPC, or where there are only non-ionizing
289  // particles, or something like that.
290  if (!event.getByLabel(fSimModuleLabel, energyDepositHandle))
291  return;
292 
293  // Define the container for the SimChannel objects that will be
294  // transferred to the art::Event after the put statement below.
295  std::unique_ptr< std::vector<sim::SimChannel> > channels(new std::vector<sim::SimChannel>);
296  // Container for the SimDriftedElectronCluster objects
297  std::unique_ptr< std::vector<sim::SimDriftedElectronCluster> > SimDriftedElectronClusterCollection( new std::vector<sim::SimDriftedElectronCluster>);
298 
299  // Clear the channel maps from the last event. Remember,
300  // fChannelMaps is an array[cryo][tpc] of maps.
301  size_t cryo = 0;
302  fChannelMaps.resize(fNCryostats);
303  for (auto& cryoData: fChannelMaps) { // each, a vector of maps
304  cryoData.resize(fNTPCs[cryo++]);
305  for (auto& channelsMap: cryoData) channelsMap.clear(); // each, a map
306  }
307 
308  // We're going through the input vector by index, rather than by
309  // iterator, because we need the index number to compute the
310  // associations near the end of this method.
311  auto const& energyDeposits = *energyDepositHandle;
312  auto energyDepositsSize = energyDeposits.size();
313 
314  // For each energy deposit in this event
315  for ( size_t edIndex = 0; edIndex < energyDepositsSize; ++edIndex )
316  {
317  auto const& energyDeposit = energyDeposits[edIndex];
318 
319  // "xyz" is the position of the energy deposit in world
320  // coordinates. Note that the units of distance in
321  // sim::SimEnergyDeposit are supposed to be cm.
322  auto const mp = energyDeposit.MidPoint();
323  double const xyz[3] = { mp.X(), mp.Y(), mp.Z() };
324 
325  // From the position in world coordinates, determine the
326  // cryostat and tpc. If somehow the step is outside a tpc
327  // (e.g., cosmic rays in rock) just move on to the next one.
328  unsigned int cryostat = 0;
329  try {
330  fGeometry->PositionToCryostat(xyz, cryostat);
331  }
332  catch(cet::exception &e){
333  mf::LogWarning("SimDriftElectrons") << "step "// << energyDeposit << "\n"
334  << "cannot be found in a cryostat\n"
335  << e;
336  continue;
337  }
338 
339  unsigned int tpc = 0;
340  try {
341  fGeometry->PositionToTPC(xyz, tpc, cryostat);
342  }
343  catch(cet::exception &e){
344  mf::LogWarning("SimDriftElectrons") << "step "// << energyDeposit << "\n"
345  << "cannot be found in a TPC\n"
346  << e;
347  continue;
348  }
349 
350  const geo::TPCGeo& tpcGeo = fGeometry->TPC(tpc, cryostat);
351 
352  // X drift distance - the drift direction can be either in
353  // the positive or negative direction, so use std::abs
354 
355 
356  if(tpcGeo.DriftDirection()==geo::kNegX && tpcGeo.PlaneLocation(0)[0]>xyz[0])
357  continue;
358  if(tpcGeo.DriftDirection()==geo::kPosX && tpcGeo.PlaneLocation(0)[0]<xyz[0])
359  continue;
360 
362  // Center of plane is also returned in cm units
363  double XDrift = std::abs(xyz[0] - tpcGeo.PlaneLocation(0)[0]);
364  //std::cout<<tpcGeo.DriftDirection()<<std::endl;
365  if (tpcGeo.DriftDirection() == geo::kNegX)
366  XDrift = xyz[0] - tpcGeo.PlaneLocation(0)[0];
367  else if (tpcGeo.DriftDirection() == geo::kPosX)
368  XDrift = tpcGeo.PlaneLocation(0)[0] - xyz[0];
369 
370  if(XDrift < 0.) continue;
371 
372  // Space-charge effect (SCE): Get SCE {x,y,z} offsets for
373  // particular location in TPC
374  geo::Vector_t posOffsets{0.0,0.0,0.0};
375  auto const* SCE = lar::providerFrom<spacecharge::SpaceChargeService>();
376  if (SCE->EnableSimSpatialSCE() == true)
377  {
378  posOffsets = SCE->GetPosOffsets(mp);
379  }
380  XDrift += -1.*posOffsets.X();
381 
382  // Space charge distortion could push the energy deposit beyond the wire
383  // plane (see issue #15131). Given that we don't have any subtlety in the
384  // simulation of this region, bringing the deposit exactly on the plane
385  // should be enough for the time being.
386  if (XDrift < 0.) XDrift = 0.;
387 
388  // Drift time in ns
389  double TDrift = XDrift * fRecipDriftVel[0];
390  if (tpcGeo.Nplanes() == 2){// special case for ArgoNeuT (plane 0 is the second wire plane)
391  TDrift = ((XDrift - tpcGeo.PlanePitch(0,1)) * fRecipDriftVel[0]
392  + tpcGeo.PlanePitch(0,1) * fRecipDriftVel[1]);
393  }
394 
395  fISAlg.Reset();
397  //std::cout << "Got " << fISAlg.NumberIonizationElectrons() << "." << std::endl;
398 
399  const double lifetimecorrection = TMath::Exp(TDrift / fLifetimeCorr_const);
400  const int nIonizedElectrons = fISAlg.NumberIonizationElectrons();
401  const double energy = energyDeposit.Energy();
402 
403  // if we have no electrons (too small energy or too large recombination)
404  // we are done already here
405  if (nIonizedElectrons <= 0) {
406  LOG_DEBUG("SimDriftElectrons")
407  << "step "// << energyDeposit << "\n"
408  << "No electrons drifted to readout, " << energy << " MeV lost.";
409  continue;
410  }
411 
412  // includes the effect of lifetime: lifetimecorrection = exp[-tdrift/tau]
413  const double nElectrons = nIonizedElectrons * lifetimecorrection;
414  //std::cout << "After lifetime, " << nElectrons << " electrons." << std::endl;
415 
416  // Longitudinal & transverse diffusion sigma (cm)
417  double SqrtT = std::sqrt(TDrift);
418  double LDiffSig = SqrtT * fLDiff_const;
419  double TDiffSig = SqrtT * fTDiff_const;
420  double electronclsize = fElectronClusterSize;
421 
422  // Number of electron clusters.
423  int nClus = (int) std::ceil(nElectrons / electronclsize);
424  if (nClus < fMinNumberOfElCluster)
425  {
426  electronclsize = nElectrons / fMinNumberOfElCluster;
427  if (electronclsize < 1.0)
428  {
429  electronclsize = 1.0;
430  }
431  nClus = (int) std::ceil(nElectrons / electronclsize);
432  }
433 
434  // Empty and resize the electron-cluster vectors.
435  fXDiff.clear();
436  fYDiff.clear();
437  fZDiff.clear();
438  fnElDiff.clear();
439  fnEnDiff.clear();
440  fXDiff.resize(nClus);
441  fYDiff.resize(nClus);
442  fZDiff.resize(nClus);
443  fnElDiff.resize(nClus, electronclsize);
444  fnEnDiff.resize(nClus);
445 
446  // fix the number of electrons in the last cluster, that has a smaller size
447  fnElDiff.back() = nElectrons - (nClus-1)*electronclsize;
448 
449  for(size_t xx = 0; xx < fnElDiff.size(); ++xx){
450  if(nElectrons > 0) fnEnDiff[xx] = energy/nElectrons*fnElDiff[xx];
451  else fnEnDiff[xx] = 0.;
452  }
453 
454  //std::cout << "Split into, " << nClus << " clusters." << std::endl;
455 
456  double const avegageYtransversePos
457  = xyz[1] + posOffsets.Y();
458  double const avegageZtransversePos
459  = xyz[2] + posOffsets.Z();
460 
461  // Smear drift times by x position and drift time
462  if (LDiffSig > 0.0)
463  fRandGauss->fireArray( nClus, &fXDiff[0], 0., LDiffSig);
464  else
465  fXDiff.assign(nClus, 0.0);
466 
467  if (TDiffSig > 0.0) {
468  // Smear the Y,Z position by the transverse diffusion
469  fRandGauss->fireArray( nClus, &fYDiff[0], avegageYtransversePos, TDiffSig);
470  fRandGauss->fireArray( nClus, &fZDiff[0], avegageZtransversePos, TDiffSig);
471  }
472  else {
473  fYDiff.assign(nClus, avegageYtransversePos);
474  fZDiff.assign(nClus, avegageZtransversePos);
475  }
476 
477  //std::cout << "Smeared the " << nClus << " clusters." << std::endl;
478 
479  // make a collection of electrons for each plane
480  for(size_t p = 0; p < tpcGeo.Nplanes(); ++p){
481 
482  //std::cout << "Doing plane " << p << std::endl;
483 
484  //geo::PlaneGeo const& plane = tpcGeo.Plane(p); // unused
485 
486  double Plane0Pitch = tpcGeo.Plane0Pitch(p);
487 
488  // "-" sign is because Plane0Pitch output is positive. Andrzej
489  fDriftClusterPos[0] = tpcGeo.PlaneLocation(0)[0] - Plane0Pitch;
490 
491  // Drift nClus electron clusters to the induction plane
492  for(int k = 0; k < nClus; ++k){
493 
494  //std::cout << "\tCluster " << k << " diffs are "
495  // << fXDiff[k] << " " << fYDiff[k] << " " << fZDiff[k]
496  // << std::endl;
497 
498  // Correct drift time for longitudinal diffusion and plane
499  double TDiff = TDrift + fXDiff[k] * fRecipDriftVel[0];
500  // Take into account different Efields between planes
501  // Also take into account special case for ArgoNeuT where Nplanes = 2.
502  for (size_t ip = 0; ip<p; ++ip){
503  TDiff += tpcGeo.PlanePitch(ip,ip+1) * fRecipDriftVel[tpcGeo.Nplanes()==3?ip+1:ip+2];
504  }
505  fDriftClusterPos[1] = fYDiff[k];
506  fDriftClusterPos[2] = fZDiff[k];
507 
509 
510  // grab the nearest channel to the fDriftClusterPos position
511  try{
512  /*
513  if (fOffPlaneMargin != 0) {
514  // get the effective position where to consider the charge landed;
515  //
516  // Some optimisations are possible; in particular, this method
517  // could be extended to inform us if the point was too far.
518  // Currently, if that is the case the code will proceed, find the
519  // point is off plane, emit a warning and skip the deposition.
520  //
521  auto const landingPos
522  = RecoverOffPlaneDeposit({ fDriftClusterPos[0], fDriftClusterPos[1], fDriftClusterPos[2] }, plane);
523  fDriftClusterPos[0] = landingPos.X();
524  fDriftClusterPos[1] = landingPos.Y();
525  fDriftClusterPos[2] = landingPos.Z();
526 
527  } // if charge lands off plane
528  */
529  raw::ChannelID_t channel = fGeometry->NearestChannel(fDriftClusterPos, p, tpc, cryostat);
530 
531  //std::cout << "\tgot channel " << channel << " for cluster " << k << std::endl;
532 
535  // Add potential decay/capture/etc delay effect, simTime.
536  auto const simTime = energyDeposit.Time();
537  unsigned int tdc = fClock.Ticks(fTimeService->G4ToElecTime(TDiff + simTime));
538 
539  // Find whether we already have this channel in our map.
540  ChannelMap_t& channelDataMap = fChannelMaps[cryostat][tpc];
541  auto search = channelDataMap.find(channel);
542 
543  // We will find (or create) the pointer to a
544  // sim::SimChannel.
545  //sim::SimChannel* channelPtr = NULL;
546  size_t channelIndex=0;
547 
548  // Have we created the sim::SimChannel corresponding to
549  // channel ID?
550  if (search == channelDataMap.end())
551  {
552  //std::cout << "\tHaven't done this channel before." << std::endl;
553 
554  // We haven't. Initialize the bookkeeping information
555  // for this channel.
556  ChannelBookKeeping_t bookKeeping;
557 
558  // Add a new channel to the end of the list we'll
559  // write out after we've processed this event.
560  bookKeeping.channelIndex = channels->size();
561  channels->emplace_back( channel );
562  channelIndex = bookKeeping.channelIndex;
563 
564  // Save the pointer to the newly-created
565  // sim::SimChannel.
566  //channelPtr = &(channels->back());
567  //bookKeeping.channelPtr = channelPtr;
568 
569  // Initialize a vector with the index of the step that
570  // created this channel.
571  bookKeeping.stepList.push_back( edIndex );
572 
573  // Save the bookkeeping information for this channel.
574  channelDataMap[channel] = bookKeeping;
575  }
576  else {
577  // We've created this SimChannel for a previous energy
578  // deposit. Get its address.
579 
580  //std::cout << "\tHave seen this channel before." << std::endl;
581 
582  auto& bookKeeping = search->second;
583  channelIndex = bookKeeping.channelIndex;
584  //channelPtr = bookKeeping.channelPtr;
585 
586  // Has this step contributed to this channel before?
587  auto& stepList = bookKeeping.stepList;
588  auto stepSearch = std::find(stepList.begin(), stepList.end(), edIndex );
589  if ( stepSearch == stepList.end() ) {
590  // No, so add this step's index to the list.
591  stepList.push_back( edIndex );
592  }
593  }
594  sim::SimChannel* channelPtr = &(channels->at(channelIndex));
595 
596  //std::cout << "\tAdding electrons to SimChannel" << std::endl;
597  //std::cout << "\t\t"
598  // << energyDeposit.TrackID() << " " << tdc
599  // << " " << xyz[0] << " " << xyz[1] << " " << xyz[2]
600  // << " " << fnEnDiff[k] << " " << fnElDiff[k]
601  // << std::endl;
602 
603  //if(!channelPtr) std::cout << "\tUmm...ptr is NULL?" << std::endl;
604  //else std::cout << "\tChannel is " << channelPtr->Channel() << std::endl;
605  // Add the electron clusters and energy to the
606  // sim::SimChannel
607  channelPtr->AddIonizationElectrons(energyDeposit.TrackID(),
608  tdc,
609  fnElDiff[k],
610  xyz,
611  fnEnDiff[k]);
612 
614  SimDriftedElectronClusterCollection->push_back(sim::SimDriftedElectronCluster(
615  fnElDiff[k],
616  TDiff + simTime, // timing
617  {mp.X(),mp.Y(),mp.Z()}, // mean position of the deposited energy
618  {fDriftClusterPos[0],fDriftClusterPos[1],fDriftClusterPos[2]}, // final position of the drifted cluster
619  {LDiffSig,TDiffSig,TDiffSig}, // Longitudinal (X) and transverse (Y,Z) diffusion
620  fnEnDiff[k], //deposited energy that originated this cluster
621  energyDeposit.TrackID()) );
622 
623  //std::cout << "\tAdded the electrons." << std::endl;
624 
625  }
626  catch(cet::exception &e) {
627  mf::LogWarning("SimDriftElectrons") << "unable to drift electrons from point ("
628  << xyz[0] << "," << xyz[1] << "," << xyz[2]
629  << ") with exception " << e;
630  } // end try to determine channel
631  } // end loop over clusters
632  } // end loop over planes
633  } // for each sim::SimEnergyDeposit
634  /*
635  // Now that we've processed the information for all the
636  // sim::SimEnergyDeposit objects into sim::SimChannel objects,
637  // create the associations between them.
638 
639  // Define the container for the associations between the channels
640  // and the energy deposits (steps). Note it's possible for an
641  // energy deposit to be associated with more than one channel (if
642  // its electrons drift to multiple wires), and a channel will
643  // almost certainly have multiple energy deposits.
644  std::unique_ptr< art::Assns<sim::SimEnergyDeposit, sim::SimChannel> >
645  step2channel (new art::Assns<sim::SimEnergyDeposit, sim::SimChannel>);
646 
647  // For every element in the 3-D fChannelMaps array...
648  for ( auto i = fChannelMaps.begin(); i != fChannelMaps.end(); ++i ) {
649  for ( auto j = i->begin(); j != i->end(); ++j ) {
650  for ( auto k = j->begin(); k != j->end(); ++k ) {
651  const ChannelBookKeeping_t& bookKeeping = (*k).second;
652  const size_t channelIndex = bookKeeping.channelIndex;
653 
654  // Create a one-to-one association between each channel and
655  // each step that created it.
656  for ( size_t m = 0; m < bookKeeping.stepList.size(); ++m)
657  {
658  const size_t edIndex = bookKeeping.stepList[m];
659  // Props to me for figuring out the following two
660  // statements. You have to look deeply in the
661  // documentation for art::Ptr and util::Associations to
662  // put this together.
663  art::Ptr<sim::SimEnergyDeposit> energyDepositPtr( energyDepositHandle, edIndex );
664  util::CreateAssn(*this, event, *channels, energyDepositPtr, *step2channel, channelIndex);
665  }
666  }
667  }
668  }
669  */
670  // Write the sim::SimChannel collection.
671  event.put(std::move(channels));
672  if (fStoreDriftedElectronClusters) event.put(std::move(SimDriftedElectronClusterCollection));
673 
674  // ... and its associations.
675  //event.put(std::move(step2channel));
676 
677  return;
678  }
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
CryostatGeo const & PositionToCryostat(geo::Point_t const &point) const
Returns the cryostat at specified location.
unsigned int Nplanes() const
Number of planes in this tpc.
Definition: TPCGeo.h:145
larg4::ISCalculationSeparate fISAlg
Geometry information for a single TPC.
Definition: TPCGeo.h:37
std::vector< std::vector< ChannelMap_t > > fChannelMaps
art::ServiceHandle< geo::Geometry > fGeometry
Handle to the Geometry service.
int Ticks() const
Current clock tick (that is, the number of tick Time() falls in).
Definition: ElecClock.h:235
Drift towards negative X values.
Definition: geo_types.h:109
geo::TPCGeo const & PositionToTPC(geo::Point_t const &point) const
Returns the TPC at specified location.
const detinfo::DetectorClocks * fTimeService
double energy
Definition: plottest35.C:25
void CalculateIonizationAndScintillation(sim::SimEnergyDeposit const &edep)
double Plane0Pitch(unsigned int p) const
Returns the center of the TPC volume in world coordinates [cm].
Definition: TPCGeo.cxx:354
virtual double G4ToElecTime(double g4_time) const =0
Given a simulation time [ns], converts it into electronics time [µs].
DriftDirection_t DriftDirection() const
Returns an enumerator value describing the drift direction.
Definition: TPCGeo.h:127
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
std::map< raw::ChannelID_t, ChannelBookKeeping_t > ChannelMap_t
Drift towards positive X values.
Definition: geo_types.h:108
::detinfo::ElecClock fClock
TPC electronics clock.
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
#define LOG_DEBUG(id)
std::unique_ptr< CLHEP::RandGauss > fRandGauss
TPCGeo const & TPC(unsigned int const tpc=0, unsigned int const cstat=0) const
Returns the specified TPC.
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
Event finding and building.
void detsim::SimDriftElectrons::reconfigure ( fhicl::ParameterSet const &  p)

Definition at line 207 of file SimDriftElectrons_module.cc.

References fSimModuleLabel, fStoreDriftedElectronClusters, fhicl::ParameterSet::get(), and label.

Referenced by SimDriftElectrons(), and ~SimDriftElectrons().

208  {
209  std::string label= p.get< std::string >("SimulationLabel");
211 
212  fStoreDriftedElectronClusters = p.get< bool >("StoreDriftedElectronClusters", false);
213 
214 
215  return;
216  }
const std::string label
void art::Consumer::showMissingConsumes ( ) const
protectedinherited

Definition at line 125 of file Consumer.cc.

Referenced by art::EDProducer::doEndJob(), art::EDFilter::doEndJob(), art::EDAnalyzer::doEndJob(), and art::RootOutput::endJob().

126 {
127  if (!moduleContext_)
128  return;
129 
130  // If none of the branches have missing consumes statements, exit early.
131  if (std::all_of(cbegin(missingConsumes_),
132  cend(missingConsumes_),
133  [](auto const& perBranch) { return perBranch.empty(); }))
134  return;
135 
136  constexpr cet::HorizontalRule rule{60};
137  mf::LogPrint log{"MTdiagnostics"};
138  log << '\n'
139  << rule('=') << '\n'
140  << "The following consumes (or mayConsume) statements are missing from\n"
141  << module_context(moduleDescription_) << '\n'
142  << rule('-') << '\n';
143 
144  cet::for_all_with_index(
145  missingConsumes_, [&log](std::size_t const i, auto const& perBranch) {
146  for (auto const& pi : perBranch) {
147  log << " "
148  << assemble_consumes_statement(static_cast<BranchType>(i), pi)
149  << '\n';
150  }
151  });
152  log << rule('=');
153 }
cet::exempt_ptr< ModuleDescription const > moduleDescription_
Definition: Consumer.h:140
constexpr T pi()
Returns the constant pi (up to 35 decimal digits of precision)
bool moduleContext_
Definition: Consumer.h:136
ConsumableProductSets missingConsumes_
Definition: Consumer.h:139
void art::Consumer::validateConsumedProduct ( BranchType const  bt,
ProductInfo const &  pi 
)
protectedinherited

Definition at line 101 of file Consumer.cc.

References art::errors::ProductRegistrationFailure.

103 {
104  // Early exits if consumes tracking has been disabled or if the
105  // consumed product is an allowed consumable.
106  if (!moduleContext_)
107  return;
108 
109  if (cet::binary_search_all(consumables_[bt], pi))
110  return;
111 
112  if (requireConsumes_) {
114  "Consumer: an error occurred during validation of a "
115  "retrieved product\n\n")
116  << "The following consumes (or mayConsume) statement is missing from\n"
117  << module_context(moduleDescription_) << ":\n\n"
118  << " " << assemble_consumes_statement(bt, pi) << "\n\n";
119  }
120 
121  missingConsumes_[bt].insert(pi);
122 }
cet::exempt_ptr< ModuleDescription const > moduleDescription_
Definition: Consumer.h:140
bool requireConsumes_
Definition: Consumer.h:137
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
Definition: Exception.h:66
constexpr T pi()
Returns the constant pi (up to 35 decimal digits of precision)
ConsumableProducts consumables_
Definition: Consumer.h:138
bool moduleContext_
Definition: Consumer.h:136
ConsumableProductSets missingConsumes_
Definition: Consumer.h:139

Member Data Documentation

std::vector< std::vector<ChannelMap_t> > detsim::SimDriftElectrons::fChannelMaps
private

Definition at line 148 of file SimDriftElectrons_module.cc.

Referenced by produce().

::detinfo::ElecClock detsim::SimDriftElectrons::fClock
private

TPC electronics clock.

Definition at line 170 of file SimDriftElectrons_module.cc.

Referenced by beginJob(), and produce().

double detsim::SimDriftElectrons::fDriftClusterPos[3]
private

Definition at line 164 of file SimDriftElectrons_module.cc.

Referenced by produce().

double detsim::SimDriftElectrons::fElectronClusterSize
private

Definition at line 119 of file SimDriftElectrons_module.cc.

Referenced by beginJob(), and produce().

double detsim::SimDriftElectrons::fElectronLifetime
private

Definition at line 118 of file SimDriftElectrons_module.cc.

Referenced by beginJob().

art::ServiceHandle<geo::Geometry> detsim::SimDriftElectrons::fGeometry
private

Handle to the Geometry service.

Definition at line 169 of file SimDriftElectrons_module.cc.

Referenced by beginJob(), and produce().

larg4::ISCalculationSeparate detsim::SimDriftElectrons::fISAlg
private

Definition at line 174 of file SimDriftElectrons_module.cc.

Referenced by beginJob(), and produce().

double detsim::SimDriftElectrons::fLDiff_const
private

Definition at line 127 of file SimDriftElectrons_module.cc.

Referenced by beginJob(), and produce().

double detsim::SimDriftElectrons::fLifetimeCorr_const
private

Definition at line 126 of file SimDriftElectrons_module.cc.

Referenced by beginJob(), and produce().

double detsim::SimDriftElectrons::fLongitudinalDiffusion
private

Definition at line 123 of file SimDriftElectrons_module.cc.

Referenced by beginJob().

int detsim::SimDriftElectrons::fMinNumberOfElCluster
private

Definition at line 120 of file SimDriftElectrons_module.cc.

Referenced by beginJob(), and produce().

size_t detsim::SimDriftElectrons::fNCryostats
private

Definition at line 154 of file SimDriftElectrons_module.cc.

Referenced by beginJob(), and produce().

std::vector< double > detsim::SimDriftElectrons::fnElDiff
private

Definition at line 161 of file SimDriftElectrons_module.cc.

Referenced by produce().

std::vector< double > detsim::SimDriftElectrons::fnEnDiff
private

Definition at line 162 of file SimDriftElectrons_module.cc.

Referenced by produce().

std::vector<size_t> detsim::SimDriftElectrons::fNTPCs
private

Definition at line 155 of file SimDriftElectrons_module.cc.

Referenced by beginJob(), and produce().

std::unique_ptr<CLHEP::RandGauss> detsim::SimDriftElectrons::fRandGauss
private

Definition at line 116 of file SimDriftElectrons_module.cc.

Referenced by beginJob(), and produce().

double detsim::SimDriftElectrons::fRecipDriftVel[3]
private

Definition at line 129 of file SimDriftElectrons_module.cc.

Referenced by beginJob(), and produce().

art::InputTag detsim::SimDriftElectrons::fSimModuleLabel
private

Definition at line 113 of file SimDriftElectrons_module.cc.

Referenced by produce(), and reconfigure().

bool detsim::SimDriftElectrons::fStoreDriftedElectronClusters
private

Definition at line 131 of file SimDriftElectrons_module.cc.

Referenced by produce(), reconfigure(), and SimDriftElectrons().

double detsim::SimDriftElectrons::fTDiff_const
private

Definition at line 128 of file SimDriftElectrons_module.cc.

Referenced by beginJob(), and produce().

const detinfo::DetectorClocks* detsim::SimDriftElectrons::fTimeService
private

Definition at line 115 of file SimDriftElectrons_module.cc.

Referenced by beginJob(), and produce().

double detsim::SimDriftElectrons::fTransverseDiffusion
private

Definition at line 124 of file SimDriftElectrons_module.cc.

Referenced by beginJob().

std::vector< double > detsim::SimDriftElectrons::fXDiff
private

Definition at line 158 of file SimDriftElectrons_module.cc.

Referenced by produce().

std::vector< double > detsim::SimDriftElectrons::fYDiff
private

Definition at line 159 of file SimDriftElectrons_module.cc.

Referenced by produce().

std::vector< double > detsim::SimDriftElectrons::fZDiff
private

Definition at line 160 of file SimDriftElectrons_module.cc.

Referenced by produce().


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