77 #include "nurandom/RandomUtils/NuRandomService.h" 80 #include "CLHEP/Random/RandGauss.h" 172 produces<std::vector<sim::SimChannel>>();
186 for (
int i = 0; i < 3; ++i) {
187 double driftVelocity = detProp.DriftVelocity(detProp.Efield(i),
188 detProp.Temperature()) *
206 <<
"\n Temperature (K): " << detProp.Temperature()
229 energyDepositHandle_t energyDepositHandle;
238 std::unique_ptr<std::vector<sim::SimChannel>>
channels(
new std::vector<sim::SimChannel>);
240 std::unique_ptr<std::vector<sim::SimDriftedElectronCluster>>
241 SimDriftedElectronClusterCollection(
new std::vector<sim::SimDriftedElectronCluster>);
251 auto const clockData =
253 auto const& tpcClock = clockData.TPCClock();
260 auto const& energyDeposits = *energyDepositHandle;
261 auto energyDepositsSize = energyDeposits.size();
264 for (
size_t edIndex = 0; edIndex < energyDepositsSize; ++edIndex) {
265 auto const& energyDeposit = energyDeposits[edIndex];
270 auto const mp = energyDeposit.MidPoint();
271 double const xyz[3] = {mp.X(), mp.Y(), mp.Z()};
276 unsigned int cryostat = 0;
282 <<
"cannot be found in a cryostat\n" 287 unsigned int tpc = 0;
293 <<
"cannot be found in a TPC\n" 315 int transversecoordinate1 = 0;
316 int transversecoordinate2 = 0;
317 if (driftcoordinate == 0) {
318 transversecoordinate1 = 1;
319 transversecoordinate2 = 2;
321 else if (driftcoordinate == 1) {
322 transversecoordinate1 = 0;
323 transversecoordinate2 = 2;
325 else if (driftcoordinate == 2) {
326 transversecoordinate1 = 0;
327 transversecoordinate2 = 1;
330 if (transversecoordinate1 == transversecoordinate2)
340 if (driftsign == 1 && tpcGeo.
PlaneLocation(0)[driftcoordinate] < xyz[driftcoordinate])
342 if (driftsign == -1 && tpcGeo.
PlaneLocation(0)[driftcoordinate] > xyz[driftcoordinate])
347 double DriftDistance =
353 double posOffsetxyz[3] = {0.0, 0.0, 0.0};
355 auto const* SCE = lar::providerFrom<spacecharge::SpaceChargeService>();
356 if (SCE->EnableSimSpatialSCE() ==
true) {
357 posOffsets = SCE->GetPosOffsets(mp);
361 posOffsetxyz[0] = posOffsets.X();
362 posOffsetxyz[1] = posOffsets.Y();
363 posOffsetxyz[2] = posOffsets.Z();
366 double avegagetransversePos1 = 0.;
367 double avegagetransversePos2 = 0.;
369 DriftDistance += -1. * posOffsetxyz[driftcoordinate];
370 avegagetransversePos1 = xyz[transversecoordinate1] + posOffsetxyz[transversecoordinate1];
371 avegagetransversePos2 = xyz[transversecoordinate2] + posOffsetxyz[transversecoordinate2];
377 if (DriftDistance < 0.) DriftDistance = 0.;
383 driftcoordinate == 0) {
385 TDrift = ((DriftDistance - tpcGeo.
PlanePitch(0, 1)) * fRecipDriftVel[0] +
391 const double energy = energyDeposit.Energy();
395 if (nIonizedElectrons <= 0) {
398 <<
"No electrons drifted to readout, " << energy <<
" MeV lost.";
403 const double nElectrons = nIonizedElectrons * lifetimecorrection;
406 double SqrtT = std::sqrt(TDrift);
412 int nClus = (
int)std::ceil(nElectrons / electronclsize);
415 if (electronclsize < 1.0) { electronclsize = 1.0; }
416 nClus = (
int)std::ceil(nElectrons / electronclsize);
428 fnElDiff.resize(nClus, electronclsize);
432 fnElDiff.back() = nElectrons - (nClus - 1) * electronclsize;
434 for (
size_t xx = 0; xx <
fnElDiff.size(); ++xx) {
447 if (TDiffSig > 0.0) {
458 for (
size_t p = 0;
p < tpcGeo.
Nplanes(); ++
p) {
463 for (
int k = 0;
k < nClus; ++
k) {
466 double TDiff = TDrift +
fLongDiff[
k] * fRecipDriftVel[0];
471 for (
size_t ip = 0; ip <
p; ++ip) {
474 fRecipDriftVel[(tpcGeo.
Nplanes() == 2 && driftcoordinate == 0) ? ip + 2 : ip + 1];
478 fDriftClusterPos[transversecoordinate2] =
fTransDiff2[
k];
490 auto const simTime = energyDeposit.Time();
491 unsigned int tdc = tpcClock.Ticks(clockData.G4ToElecTime(TDiff + simTime));
495 auto search = channelDataMap.find(channel);
499 size_t channelIndex = 0;
503 if (
search == channelDataMap.end()) {
511 channels->emplace_back(channel);
516 bookKeeping.
stepList.push_back(edIndex);
519 channelDataMap[
channel] = bookKeeping;
525 auto& bookKeeping =
search->second;
526 channelIndex = bookKeeping.channelIndex;
529 auto& stepList = bookKeeping.stepList;
530 auto stepSearch = std::find(stepList.begin(), stepList.end(), edIndex);
531 if (stepSearch == stepList.end()) {
533 stepList.push_back(edIndex);
545 SimDriftedElectronClusterCollection->emplace_back(
551 fDriftClusterPos[2]},
553 LDiffSig, TDiffSig, TDiffSig},
555 energyDeposit.TrackID());
559 <<
"unable to drift electrons from point (" << xyz[0] <<
"," << xyz[1] <<
"," 560 << xyz[2] <<
") with exception " <<
e;
Store parameters for running LArG4.
std::vector< double > fTransDiff2
double PlanePitch(unsigned int p1=0, unsigned int p2=1) const
double fElectronClusterSize
Energy deposited on a readout channel by simulated tracks.
contains objects relating to SimDriftedElectronCluster
CryostatGeo const & PositionToCryostat(geo::Point_t const &point) const
Returns the cryostat at specified location.
bool out_of_bounds(geo::Vector_t const &offset)
unsigned int Nplanes() const
Number of planes in this tpc.
EDProducer(fhicl::ParameterSet const &pset)
Geometry information for a single TPC.
std::vector< size_t > stepList
Detector simulation of raw signals on wires.
ISCalcData CalcIonAndScint(detinfo::DetectorPropertiesData const &detProp, sim::SimEnergyDeposit const &edep) override
ROOT::Math::DisplacementVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Vector_t
Type for representation of momenta in 3D space.
CLHEP::RandGauss fRandGauss
unsigned int Ncryostats() const
Returns the number of cryostats in the detector.
art::ServiceHandle< geo::Geometry const > fGeometry
Handle to the Geometry service.
art framework interface to geometry description
std::vector< size_t > fNTPCs
geo::TPCGeo const & PositionToTPC(geo::Point_t const &point) const
Returns the TPC at specified location.
double fLongitudinalDiffusion
double TransverseDiffusion() const
bool getByLabel(std::string const &label, std::string const &instance, Handle< PROD > &result) const
#define DEFINE_ART_MODULE(klass)
Utility function for testing if Space Charge offsets are out of bounds.
double ElectronClusterSize() const
larg4::ISCalcSeparate fISAlg
void produce(art::Event &evt) override
std::vector< double > fnEnDiff
std::vector< ChannelMap_t > fChannelMaps
double fTransverseDiffusion
art::InputTag fSimModuleLabel
double fLifetimeCorr_const
std::vector< double > fLongDiff
unsigned int NTPC(unsigned int cstat=0) const
Returns the total number of TPCs in the specified cryostat.
void AddIonizationElectrons(TrackID_t trackID, TDC_t tdc, double numberElectrons, double const *xyz, double energy)
Add ionization electrons and energy to this channel.
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
std::map< raw::ChannelID_t, ChannelBookKeeping > ChannelMap_t
double fDriftClusterPos[3]
std::vector< double > fTransDiff1
int MinNumberOfElCluster() const
short int DetectDriftDirection() const
Returns the expected drift direction based on geometry.
MaybeLogger_< ELseverityLevel::ELsev_success, false > LogDebug
contains information for a single step in the detector simulation
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
std::vector< double > fnElDiff
TPCGeo const & TPC(unsigned int const tpc=0, unsigned int const cstat=0) const
Returns the specified TPC.
double LongitudinalDiffusion() const
unsigned int ChannelID_t
Type representing the ID of a readout channel.
bool fStoreDriftedElectronClusters
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.
int fMinNumberOfElCluster
const double * PlaneLocation(unsigned int p) const
cet::coded_exception< error, detail::translate > exception
SimDriftElectrons(fhicl::ParameterSet const &pset)
Event finding and building.