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()) {
506 ChannelBookKeeping bookKeeping;
510 bookKeeping.channelIndex =
channels->size();
512 channelIndex = bookKeeping.channelIndex;
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;
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.
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.
Geometry information for a single TPC.
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
art::ServiceHandle< geo::Geometry const > fGeometry
Handle to the Geometry service.
geo::TPCGeo const & PositionToTPC(geo::Point_t const &point) const
Returns the TPC at specified location.
larg4::ISCalcSeparate fISAlg
std::vector< double > fnEnDiff
std::vector< ChannelMap_t > fChannelMaps
art::InputTag fSimModuleLabel
double fLifetimeCorr_const
std::vector< double > fLongDiff
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
short int DetectDriftDirection() const
Returns the expected drift direction based on geometry.
MaybeLogger_< ELseverityLevel::ELsev_success, false > LogDebug
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.
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
Event finding and building.