File indexing completed on 2024-04-06 12:11:21
0001 #include <memory>
0002
0003 #include <memory>
0004 #include <vector>
0005
0006
0007 #include "FWCore/Framework/interface/Event.h"
0008 #include "FWCore/Framework/interface/ProducesCollector.h"
0009 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0010 #include "MagneticField/UniformEngine/interface/UniformMagneticField.h"
0011
0012
0013 #include "TrackingTools/DetLayers/interface/DetLayer.h"
0014 #include "TrackingTools/GeomPropagators/interface/AnalyticalPropagator.h"
0015 #include "TrackingTools/TrajectoryState/interface/TrajectoryStateOnSurface.h"
0016 #include "TrackingTools/GeomPropagators/interface/AnalyticalPropagator.h"
0017 #include "TrackingTools/GeomPropagators/interface/HelixArbitraryPlaneCrossing.h"
0018
0019
0020 #include "FastSimulation/TrajectoryManager/interface/InsideBoundsMeasurementEstimator.h" //TODO move this
0021 #include "FastSimulation/SimplifiedGeometryPropagator/interface/Particle.h"
0022 #include "FastSimulation/SimplifiedGeometryPropagator/interface/SimplifiedGeometry.h"
0023 #include "FastSimulation/SimplifiedGeometryPropagator/interface/InteractionModel.h"
0024 #include "FastSimulation/SimplifiedGeometryPropagator/interface/InteractionModelFactory.h"
0025 #include "FastSimulation/SimplifiedGeometryPropagator/interface/Constants.h"
0026
0027
0028 #include "DataFormats/GeometrySurface/interface/Plane.h"
0029 #include "DataFormats/GeometryVector/interface/GlobalVector.h"
0030 #include "DataFormats/GeometryVector/interface/GlobalPoint.h"
0031 #include "DataFormats/GeometryVector/interface/LocalVector.h"
0032 #include "DataFormats/GeometryVector/interface/LocalPoint.h"
0033 #include "SimDataFormats/TrackingHit/interface/PSimHit.h"
0034 #include "SimDataFormats/TrackingHit/interface/PSimHitContainer.h"
0035
0036
0037 #include "Geometry/CommonDetUnit/interface/GeomDet.h"
0038 #include "CondFormats/External/interface/DetID.h"
0039
0040
0041
0042
0043
0044
0045 typedef std::pair<const GeomDet*, TrajectoryStateOnSurface> DetWithState;
0046
0047 namespace fastsim {
0048
0049
0050
0051
0052
0053
0054 class TrackerSimHitProducer : public InteractionModel {
0055 public:
0056
0057 TrackerSimHitProducer(const std::string& name, const edm::ParameterSet& cfg);
0058
0059
0060 ~TrackerSimHitProducer() override { ; }
0061
0062
0063
0064
0065
0066
0067
0068
0069 void interact(Particle& particle,
0070 const SimplifiedGeometry& layer,
0071 std::vector<std::unique_ptr<Particle>>& secondaries,
0072 const RandomEngineAndDistribution& random) override;
0073
0074
0075 void registerProducts(edm::ProducesCollector) const override;
0076
0077
0078 void storeProducts(edm::Event& iEvent) override;
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091 std::pair<double, std::unique_ptr<PSimHit>> createHitOnDetector(const TrajectoryStateOnSurface& particle,
0092 int pdgId,
0093 double layerThickness,
0094 double eLoss,
0095 int simTrackId,
0096 const GeomDet& detector,
0097 GlobalPoint& refPos);
0098
0099 private:
0100 const double
0101 onSurfaceTolerance_;
0102 std::unique_ptr<edm::PSimHitContainer> simHitContainer_;
0103 double minMomentum_;
0104 bool doHitsFromInboundParticles_;
0105 };
0106 }
0107
0108 fastsim::TrackerSimHitProducer::TrackerSimHitProducer(const std::string& name, const edm::ParameterSet& cfg)
0109 : fastsim::InteractionModel(name), onSurfaceTolerance_(0.01), simHitContainer_(new edm::PSimHitContainer) {
0110
0111 minMomentum_ = cfg.getParameter<double>("minMomentumCut");
0112
0113
0114
0115 doHitsFromInboundParticles_ = cfg.getParameter<bool>("doHitsFromInboundParticles");
0116 }
0117
0118 void fastsim::TrackerSimHitProducer::registerProducts(edm::ProducesCollector producesCollector) const {
0119 producesCollector.produces<edm::PSimHitContainer>("TrackerHits");
0120 }
0121
0122 void fastsim::TrackerSimHitProducer::storeProducts(edm::Event& iEvent) {
0123 iEvent.put(std::move(simHitContainer_), "TrackerHits");
0124 simHitContainer_ = std::make_unique<edm::PSimHitContainer>();
0125 }
0126
0127 void fastsim::TrackerSimHitProducer::interact(Particle& particle,
0128 const SimplifiedGeometry& layer,
0129 std::vector<std::unique_ptr<Particle>>& secondaries,
0130 const RandomEngineAndDistribution& random) {
0131
0132 double energyDeposit = particle.getEnergyDeposit();
0133 particle.setEnergyDeposit(0);
0134
0135
0136
0137
0138 if (!doHitsFromInboundParticles_) {
0139 if (particle.isLooper()) {
0140 return;
0141 }
0142 if (particle.momentum().X() * particle.position().X() + particle.momentum().Y() * particle.position().Y() < 0) {
0143 particle.setLooper();
0144 return;
0145 }
0146 if (layer.isForward() && ((particle.position().Z() > 0 && particle.momentum().Z() < 0) ||
0147 (particle.position().Z() < 0 && particle.momentum().Z() > 0))) {
0148 particle.setLooper();
0149 return;
0150 }
0151 }
0152
0153
0154
0155
0156 if (!layer.getDetLayer()) {
0157 return;
0158 }
0159
0160
0161
0162
0163 if (layer.getThickness(particle.position(), particle.momentum()) < 1E-10) {
0164 return;
0165 }
0166
0167
0168
0169
0170 if (particle.charge() == 0) {
0171 return;
0172 }
0173
0174
0175
0176
0177 if (particle.momentum().Perp2() < minMomentum_ * minMomentum_) {
0178 return;
0179 }
0180
0181
0182 UniformMagneticField magneticField(layer.getMagneticFieldZ(particle.position()));
0183 GlobalPoint position(particle.position().X(), particle.position().Y(), particle.position().Z());
0184 GlobalVector momentum(particle.momentum().Px(), particle.momentum().Py(), particle.momentum().Pz());
0185 auto plane = layer.getDetLayer()->surface().tangentPlane(position);
0186 TrajectoryStateOnSurface trajectory(
0187 GlobalTrajectoryParameters(position, momentum, TrackCharge(particle.charge()), &magneticField), *plane);
0188
0189
0190 AnalyticalPropagator propagator(&magneticField, anyDirection);
0191 InsideBoundsMeasurementEstimator est;
0192 std::vector<DetWithState> compatibleDetectors = layer.getDetLayer()->compatibleDets(trajectory, propagator, est);
0193
0194
0195
0196
0197
0198
0199
0200
0201
0202 std::map<double, std::unique_ptr<PSimHit>> distAndHits;
0203
0204 GlobalPoint positionOutside(particle.position().x() - particle.momentum().x() / particle.momentum().P() * 10.,
0205 particle.position().y() - particle.momentum().y() / particle.momentum().P() * 10.,
0206 particle.position().z() - particle.momentum().z() / particle.momentum().P() * 10.);
0207
0208
0209 int pdgId = particle.pdgId();
0210 int simTrackId =
0211 particle.getMotherSimTrackIndex() >= 0 ? particle.getMotherSimTrackIndex() : particle.simTrackIndex();
0212
0213
0214 for (const auto& detectorWithState : compatibleDetectors) {
0215 const GeomDet& detector = *detectorWithState.first;
0216 const TrajectoryStateOnSurface& particleState = detectorWithState.second;
0217
0218
0219 if (detector.isLeaf()) {
0220 std::pair<double, std::unique_ptr<PSimHit>> hitPair = createHitOnDetector(particleState,
0221 pdgId,
0222 layer.getThickness(particle.position()),
0223 energyDeposit,
0224 simTrackId,
0225 detector,
0226 positionOutside);
0227 if (hitPair.second) {
0228 distAndHits.insert(distAndHits.end(), std::move(hitPair));
0229 }
0230 } else {
0231
0232 for (const auto component : detector.components()) {
0233 std::pair<double, std::unique_ptr<PSimHit>> hitPair =
0234 createHitOnDetector(particleState,
0235 pdgId,
0236 layer.getThickness(particle.position()),
0237 energyDeposit,
0238 simTrackId,
0239 *component,
0240 positionOutside);
0241 if (hitPair.second) {
0242 distAndHits.insert(distAndHits.end(), std::move(hitPair));
0243 }
0244 }
0245 }
0246 }
0247
0248
0249 for (std::map<double, std::unique_ptr<PSimHit>>::const_iterator it = distAndHits.begin(); it != distAndHits.end();
0250 it++) {
0251 simHitContainer_->push_back(*(it->second));
0252 }
0253 }
0254
0255
0256 std::pair<double, std::unique_ptr<PSimHit>> fastsim::TrackerSimHitProducer::createHitOnDetector(
0257 const TrajectoryStateOnSurface& particle,
0258 int pdgId,
0259 double layerThickness,
0260 double eLoss,
0261 int simTrackId,
0262 const GeomDet& detector,
0263 GlobalPoint& refPos) {
0264
0265 LocalPoint localPosition;
0266 LocalVector localMomentum;
0267
0268
0269 if (fabs(detector.toLocal(particle.globalPosition()).z()) < onSurfaceTolerance_) {
0270 localPosition = particle.localPosition();
0271 localMomentum = particle.localMomentum();
0272 }
0273
0274 else {
0275
0276 HelixArbitraryPlaneCrossing crossing(particle.globalPosition().basicVector(),
0277 particle.globalMomentum().basicVector(),
0278 particle.transverseCurvature(),
0279 anyDirection);
0280 std::pair<bool, double> path = crossing.pathLength(detector.surface());
0281
0282 if (path.first) {
0283 localPosition = detector.toLocal(GlobalPoint(crossing.position(path.second)));
0284 localMomentum = detector.toLocal(GlobalVector(crossing.direction(path.second)));
0285 localMomentum = localMomentum.unit() * particle.localMomentum().mag();
0286 }
0287
0288 else {
0289 return std::pair<double, std::unique_ptr<PSimHit>>(0, std::unique_ptr<PSimHit>(nullptr));
0290 }
0291 }
0292
0293
0294 const Plane& detectorPlane = detector.surface();
0295 double halfThick = 0.5 * detectorPlane.bounds().thickness();
0296 double pZ = localMomentum.z();
0297 LocalPoint entry = localPosition + (-halfThick / pZ) * localMomentum;
0298 LocalPoint exit = localPosition + (halfThick / pZ) * localMomentum;
0299 double tof = particle.globalPosition().mag() / fastsim::Constants::speedOfLight;
0300
0301
0302 double boundX = detectorPlane.bounds().width() / 2.;
0303 double boundY = detectorPlane.bounds().length() / 2.;
0304
0305 unsigned subdet = DetId(detector.geographicalId()).subdetId();
0306 if (subdet == 4 || subdet == 6)
0307 boundX *= 1. - localPosition.y() / detectorPlane.position().perp();
0308 if (fabs(localPosition.x()) > boundX || fabs(localPosition.y()) > boundY) {
0309 return std::pair<double, std::unique_ptr<PSimHit>>(0, std::unique_ptr<PSimHit>(nullptr));
0310 }
0311
0312
0313
0314
0315
0316 eLoss *= (2. * halfThick - 0.003) / (9.36 * layerThickness);
0317
0318
0319 GlobalPoint hitPos(detector.surface().toGlobal(localPosition));
0320
0321 return std::pair<double, std::unique_ptr<PSimHit>>((hitPos - refPos).mag(),
0322 std::make_unique<PSimHit>(entry,
0323 exit,
0324 localMomentum.mag(),
0325 tof,
0326 eLoss,
0327 pdgId,
0328 detector.geographicalId().rawId(),
0329 simTrackId,
0330 localMomentum.theta(),
0331 localMomentum.phi()));
0332 }
0333
0334 DEFINE_EDM_PLUGIN(fastsim::InteractionModelFactory, fastsim::TrackerSimHitProducer, "fastsim::TrackerSimHitProducer");