214 energyDepositHandle_t energyDepositHandle;
222 std::unique_ptr<std::vector<sim::SimChannel>> channels(
new std::vector<sim::SimChannel>);
224 std::unique_ptr<std::vector<sim::SimDriftedElectronCluster>>
225 SimDriftedElectronClusterCollection(
new std::vector<sim::SimDriftedElectronCluster>);
235 auto const clockData =
237 auto const& tpcClock = clockData.TPCClock();
243 auto const& energyDeposits = *energyDepositHandle;
244 auto energyDepositsSize = energyDeposits.size();
248 for (
size_t edIndex = 0; edIndex < energyDepositsSize; ++edIndex) {
249 auto const& energyDeposit = energyDeposits[edIndex];
253 auto const mp = energyDeposit.MidPoint();
254 std::array<double, 3> xyz;
255 mp.GetCoordinates(data(xyz));
260 unsigned int cryostat = 0;
264 <<
"cannot be found in a cryostat\n";
272 <<
"cannot be found in a TPC\n";
277 unsigned int const nplanes = wireReadoutGeom.Nplanes(tpcid);
288 int driftcoordinate = 0;
289 int transversecoordinate1 = 1;
290 int transversecoordinate2 = 2;
292 transversecoordinate1 = 0;
294 transversecoordinate2 = 2;
297 transversecoordinate1 = 0;
298 transversecoordinate2 = 1;
305 auto const& plane_location = wireReadoutGeom.FirstPlane(tpcid).GetCenter();
306 auto const plane_location_coord =
geo::vect::coord(plane_location, driftcoordinate);
307 if (driftsign == 1 && plane_location_coord < xyz[driftcoordinate])
continue;
308 if (driftsign == -1 && plane_location_coord > xyz[driftcoordinate])
continue;
312 double DriftDistance =
std::abs(xyz[driftcoordinate] - plane_location_coord);
316 double posOffsetxyz[3] = {0.0, 0.0, 0.0};
318 auto const* SCE = lar::providerFrom<spacecharge::SpaceChargeService>();
319 if (SCE->EnableSimSpatialSCE() ==
true) {
320 posOffsets = SCE->GetPosOffsets(mp);
322 posOffsetxyz[0] = posOffsets.X();
323 posOffsetxyz[1] = posOffsets.Y();
324 posOffsetxyz[2] = posOffsets.Z();
327 double avegagetransversePos1 = 0.;
328 double avegagetransversePos2 = 0.;
330 DriftDistance += -1. * posOffsetxyz[driftcoordinate];
331 avegagetransversePos1 = xyz[transversecoordinate1] + posOffsetxyz[transversecoordinate1];
332 avegagetransversePos2 = xyz[transversecoordinate2] + posOffsetxyz[transversecoordinate2];
338 if (DriftDistance < 0.) DriftDistance = 0.;
344 driftcoordinate == 0) {
346 double const pitch = wireReadoutGeom.PlanePitch(tpcid, 0, 1);
347 TDrift = ((DriftDistance - pitch) * fRecipDriftVel[0] + pitch * fRecipDriftVel[1]);
350 const int nIonizedElectrons = energyDeposit.NumElectrons();
352 const double energy = energyDeposit.Energy();
356 if (nIonizedElectrons <= 0) {
359 <<
"No electrons drifted to readout, " << energy <<
" MeV lost.";
364 const double nElectrons = nIonizedElectrons * lifetimecorrection;
367 double SqrtT = std::sqrt(TDrift);
373 int nClus = (int)std::ceil(nElectrons / electronclsize);
376 if (electronclsize < 1.0) { electronclsize = 1.0; }
377 nClus = (int)std::ceil(nElectrons / electronclsize);
389 fnElDiff.resize(nClus, electronclsize);
393 fnElDiff.back() = nElectrons - (nClus - 1) * electronclsize;
408 if (TDiffSig > 0.0) {
419 for (
unsigned int p = 0; p < nplanes; ++p) {
426 for (
int k = 0; k < nClus; ++k) {
429 double TDiff = TDrift +
fLongDiff[k] * fRecipDriftVel[0];
434 for (
unsigned int ip = 0; ip < p; ++ip) {
435 TDiff += wireReadoutGeom.PlanePitch(tpcid, ip + 1, ip) *
436 fRecipDriftVel[(nplanes == 2 && driftcoordinate == 0) ? ip + 2 : ip + 1];
440 fDriftClusterPos[transversecoordinate2] =
fTransDiff2[k];
452 auto const simTime = energyDeposit.Time();
453 unsigned int tdc = tpcClock.Ticks(clockData.G4ToElecTime(TDiff + simTime));
457 auto search = channelDataMap.find(channel);
460 size_t channelIndex = 0;
463 if (search == channelDataMap.end()) {
465 ChannelBookKeeping bookKeeping;
469 bookKeeping.channelIndex = channels->size();
470 channels->emplace_back(channel);
471 channelIndex = bookKeeping.channelIndex;
474 bookKeeping.stepList.push_back(edIndex);
477 channelDataMap[channel] = bookKeeping;
483 auto& bookKeeping = search->second;
484 channelIndex = bookKeeping.channelIndex;
487 auto& stepList = bookKeeping.stepList;
488 if (!std::binary_search(stepList.begin(), stepList.end(), edIndex)) {
490 stepList.push_back(edIndex);
503 energyDeposit.OrigTrackID());
505 SimDriftedElectronClusterCollection->emplace_back(
511 fDriftClusterPos[2]},
513 LDiffSig, TDiffSig, TDiffSig},
515 energyDeposit.TrackID());
519 <<
"unable to drift electrons from point (" << xyz[0] <<
"," << xyz[1] <<
"," 520 << xyz[2] <<
") with exception " <<
e;
527 event.put(std::move(channels));
std::vector< double > fTransDiff2
double fElectronClusterSize
Energy deposited on a readout channel by simulated tracks.
ROOT::Math::DisplacementVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Vector_t
Type for representation of momenta in 3D space.
bool out_of_bounds(geo::Vector_t const &offset)
auto coord(Vector &v, unsigned int n) noexcept
Returns an object to manage the coordinate n of a vector.
The data type to uniquely identify a Plane.
Geometry information for a single TPC.
constexpr auto abs(T v)
Returns the absolute value of the argument.
CryostatID_t Cryostat
Index of cryostat.
cout<< "Opened file "<< fin<< " ixs= "<< ixs<< endl;if(ixs==0) hhh=(TH1F *) fff-> Get("h1")
CLHEP::RandGauss fRandGauss
DriftAxis DriftAxisWithSign() const
Returns the expected drift direction based on geometry.
art::ServiceHandle< geo::Geometry const > fGeometry
Handle to the Geometry service.
static constexpr CryostatID_t getInvalidID()
Return the value of the invalid ID as a r-value.
static constexpr TPCID_t getInvalidID()
Return the value of the invalid TPC ID as a r-value.
constexpr int to_int(Coordinate const coord) noexcept
Enumerate the possible plane projections.
Point_t toPoint(Point const &p)
Convert the specified point into a geo::Point_t.
std::vector< double > fnEnDiff
The data type to uniquely identify a TPC.
std::vector< ChannelMap_t > fChannelMaps
art::InputTag fSimModuleLabel
double fLifetimeCorr_const
std::vector< double > fLongDiff
CryostatID PositionToCryostatID(Point_t const &point) const
Returns the ID of the cryostat at specified location.
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
double fDriftClusterPos[3]
std::vector< double > fTransDiff1
MaybeLogger_< ELseverityLevel::ELsev_success, false > LogDebug
MaybeLogger_< ELseverityLevel::ELsev_warning, false > LogWarning
std::vector< double > fnElDiff
void AddIonizationElectrons(TrackID_t trackID, TDC_t tdc, double numberElectrons, double const *xyz, double energy, TrackID_t origTrackID=util::kBogusI)
Add ionization electrons and energy to this channel.
std::unordered_map< raw::ChannelID_t, ChannelBookKeeping > ChannelMap_t
unsigned int ChannelID_t
Type representing the ID of a readout channel.
TPCID_t TPC
Index of the TPC within its cryostat.
bool fStoreDriftedElectronClusters
TPCGeo const & TPC(TPCID const &tpcid=details::tpc_zero) const
Returns the specified TPC.
int fMinNumberOfElCluster
TPCID PositionToTPCID(Point_t const &point) const
Returns the ID of the TPC at specified location.
cet::coded_exception< error, detail::translate > exception
Event finding and building.