File indexing completed on 2024-04-06 12:11:20
0001
0002 #include <memory>
0003 #include <string>
0004
0005
0006 #include "FWCore/Framework/interface/ConsumesCollector.h"
0007 #include "FWCore/Framework/interface/Frameworkfwd.h"
0008 #include "FWCore/Framework/interface/stream/EDProducer.h"
0009 #include "FWCore/Framework/interface/EventSetup.h"
0010 #include "FWCore/Framework/interface/Event.h"
0011 #include "FWCore/Framework/interface/MakerMacros.h"
0012 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0013 #include "FWCore/Utilities/interface/StreamID.h"
0014 #include "FWCore/Framework/interface/LuminosityBlock.h"
0015 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0016 #include "FWCore/Framework/interface/ESWatcher.h"
0017
0018
0019 #include "SimDataFormats/GeneratorProducts/interface/HepMCProduct.h"
0020 #include "SimDataFormats/TrackingHit/interface/PSimHitContainer.h"
0021 #include "SimDataFormats/Track/interface/SimTrackContainer.h"
0022 #include "SimDataFormats/Vertex/interface/SimVertexContainer.h"
0023 #include "DataFormats/Common/interface/Handle.h"
0024 #include "DataFormats/Math/interface/LorentzVector.h"
0025
0026
0027 #include "FastSimulation/Utilities/interface/RandomEngineAndDistribution.h"
0028 #include "FastSimulation/SimplifiedGeometryPropagator/interface/Geometry.h"
0029 #include "FastSimulation/SimplifiedGeometryPropagator/interface/SimplifiedGeometry.h"
0030 #include "FastSimulation/SimplifiedGeometryPropagator/interface/Decayer.h"
0031 #include "FastSimulation/SimplifiedGeometryPropagator/interface/LayerNavigator.h"
0032 #include "FastSimulation/SimplifiedGeometryPropagator/interface/Particle.h"
0033 #include "FastSimulation/SimplifiedGeometryPropagator/interface/ParticleFilter.h"
0034 #include "FastSimulation/SimplifiedGeometryPropagator/interface/InteractionModel.h"
0035 #include "FastSimulation/SimplifiedGeometryPropagator/interface/InteractionModelFactory.h"
0036 #include "FastSimulation/SimplifiedGeometryPropagator/interface/ParticleManager.h"
0037 #include "FastSimulation/Particle/interface/makeParticle.h"
0038
0039
0040 #include "FastSimulation/Event/interface/FSimTrack.h"
0041 #include "FastSimulation/Calorimetry/interface/CalorimetryManager.h"
0042 #include "FastSimulation/CaloGeometryTools/interface/CaloGeometryHelper.h"
0043 #include "Geometry/Records/interface/CaloGeometryRecord.h"
0044 #include "Geometry/CaloGeometry/interface/CaloGeometry.h"
0045 #include "Geometry/Records/interface/CaloTopologyRecord.h"
0046 #include "FastSimulation/ShowerDevelopment/interface/FastHFShowerLibrary.h"
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064 class FastSimProducer : public edm::stream::EDProducer<> {
0065 public:
0066 explicit FastSimProducer(const edm::ParameterSet&);
0067 ~FastSimProducer() override { ; }
0068
0069 private:
0070 void beginStream(edm::StreamID id) override;
0071 void produce(edm::Event&, const edm::EventSetup&) override;
0072 void endStream() override;
0073 virtual FSimTrack createFSimTrack(fastsim::Particle* particle,
0074 fastsim::ParticleManager* particleManager,
0075 HepPDT::ParticleDataTable const& particleTable);
0076
0077 edm::EDGetTokenT<edm::HepMCProduct> genParticlesToken_;
0078 fastsim::Geometry geometry_;
0079 fastsim::Geometry caloGeometry_;
0080 double beamPipeRadius_;
0081 double deltaRchargedMother_;
0082 fastsim::ParticleFilter particleFilter_;
0083 std::unique_ptr<RandomEngineAndDistribution> _randomEngine;
0084
0085 bool simulateCalorimetry;
0086 edm::ESWatcher<CaloGeometryRecord> watchCaloGeometry_;
0087 edm::ESWatcher<CaloTopologyRecord> watchCaloTopology_;
0088 std::unique_ptr<CalorimetryManager> myCalorimetry;
0089 bool simulateMuons;
0090 bool useFastSimsDecayer;
0091
0092 fastsim::Decayer decayer_;
0093 std::vector<std::unique_ptr<fastsim::InteractionModel> > interactionModels_;
0094 std::map<std::string, fastsim::InteractionModel*> interactionModelMap_;
0095 static const std::string MESSAGECATEGORY;
0096 const edm::ESGetToken<HepPDT::ParticleDataTable, edm::DefaultRecord> particleDataTableESToken_;
0097 edm::ESGetToken<CaloGeometry, CaloGeometryRecord> caloGeometryESToken_;
0098 edm::ESGetToken<CaloTopology, CaloTopologyRecord> caloTopologyESToken_;
0099 };
0100
0101 const std::string FastSimProducer::MESSAGECATEGORY = "FastSimulation";
0102
0103 FastSimProducer::FastSimProducer(const edm::ParameterSet& iConfig)
0104 : genParticlesToken_(consumes<edm::HepMCProduct>(iConfig.getParameter<edm::InputTag>("src"))),
0105 geometry_(iConfig.getParameter<edm::ParameterSet>("trackerDefinition"), consumesCollector()),
0106 caloGeometry_(iConfig.getParameter<edm::ParameterSet>("caloDefinition"), consumesCollector()),
0107 beamPipeRadius_(iConfig.getParameter<double>("beamPipeRadius")),
0108 deltaRchargedMother_(iConfig.getParameter<double>("deltaRchargedMother")),
0109 particleFilter_(iConfig.getParameter<edm::ParameterSet>("particleFilter")),
0110 _randomEngine(nullptr),
0111 simulateCalorimetry(iConfig.getParameter<bool>("simulateCalorimetry")),
0112 simulateMuons(iConfig.getParameter<bool>("simulateMuons")),
0113 useFastSimsDecayer(iConfig.getParameter<bool>("useFastSimsDecayer")),
0114 particleDataTableESToken_(esConsumes()) {
0115 if (simulateCalorimetry) {
0116 caloGeometryESToken_ = esConsumes();
0117 caloTopologyESToken_ = esConsumes();
0118 }
0119
0120
0121
0122
0123
0124 const edm::ParameterSet& modelCfgs = iConfig.getParameter<edm::ParameterSet>("interactionModels");
0125 for (const std::string& modelName : modelCfgs.getParameterNames()) {
0126 const edm::ParameterSet& modelCfg = modelCfgs.getParameter<edm::ParameterSet>(modelName);
0127 std::string modelClassName(modelCfg.getParameter<std::string>("className"));
0128
0129 std::unique_ptr<fastsim::InteractionModel> interactionModel(
0130 fastsim::InteractionModelFactory::get()->create(modelClassName, modelName, modelCfg));
0131 if (!interactionModel.get()) {
0132 throw cms::Exception("FastSimProducer") << "InteractionModel " << modelName << " could not be created";
0133 }
0134
0135 interactionModels_.push_back(std::move(interactionModel));
0136
0137 interactionModelMap_[modelName] = interactionModels_.back().get();
0138 }
0139
0140
0141
0142
0143
0144 if (simulateCalorimetry) {
0145 myCalorimetry =
0146 std::make_unique<CalorimetryManager>(nullptr,
0147 iConfig.getParameter<edm::ParameterSet>("Calorimetry"),
0148 iConfig.getParameter<edm::ParameterSet>("MaterialEffectsForMuonsInECAL"),
0149 iConfig.getParameter<edm::ParameterSet>("MaterialEffectsForMuonsInHCAL"),
0150 iConfig.getParameter<edm::ParameterSet>("GFlash"),
0151 consumesCollector());
0152 }
0153
0154
0155
0156
0157
0158
0159 produces<edm::SimTrackContainer>();
0160 produces<edm::SimVertexContainer>();
0161
0162 for (auto& interactionModel : interactionModels_) {
0163 interactionModel->registerProducts(producesCollector());
0164 }
0165 produces<edm::PCaloHitContainer>("EcalHitsEB");
0166 produces<edm::PCaloHitContainer>("EcalHitsEE");
0167 produces<edm::PCaloHitContainer>("EcalHitsES");
0168 produces<edm::PCaloHitContainer>("HcalHits");
0169 produces<edm::SimTrackContainer>("MuonSimTracks");
0170 }
0171
0172 void FastSimProducer::beginStream(const edm::StreamID id) {
0173 _randomEngine = std::make_unique<RandomEngineAndDistribution>(id);
0174 }
0175
0176 void FastSimProducer::produce(edm::Event& iEvent, const edm::EventSetup& iSetup) {
0177 LogDebug(MESSAGECATEGORY) << " produce";
0178
0179 geometry_.update(iSetup, interactionModelMap_);
0180 caloGeometry_.update(iSetup, interactionModelMap_);
0181
0182
0183 std::unique_ptr<edm::SimTrackContainer> simTracks_(new edm::SimTrackContainer);
0184 std::unique_ptr<edm::SimVertexContainer> simVertices_(new edm::SimVertexContainer);
0185
0186
0187 auto const& pdt = iSetup.getData(particleDataTableESToken_);
0188
0189
0190 edm::Handle<edm::HepMCProduct> genParticles;
0191 iEvent.getByToken(genParticlesToken_, genParticles);
0192
0193
0194
0195 fastsim::ParticleManager particleManager(*genParticles->GetEvent(),
0196 pdt,
0197 beamPipeRadius_,
0198 deltaRchargedMother_,
0199 particleFilter_,
0200 *simTracks_,
0201 *simVertices_,
0202 useFastSimsDecayer);
0203
0204
0205 if (simulateCalorimetry) {
0206
0207 auto newGeom = watchCaloGeometry_.check(iSetup);
0208 auto newTopo = watchCaloTopology_.check(iSetup);
0209 if (newGeom || newTopo) {
0210 auto const& pG = iSetup.getData(caloGeometryESToken_);
0211 myCalorimetry->getCalorimeter()->setupGeometry(pG);
0212
0213 auto const& theCaloTopology = iSetup.getData(caloTopologyESToken_);
0214 myCalorimetry->getCalorimeter()->setupTopology(theCaloTopology);
0215 myCalorimetry->getCalorimeter()->initialize(geometry_.getMagneticFieldZ(math::XYZTLorentzVector(0., 0., 0., 0.)));
0216
0217 myCalorimetry->getHFShowerLibrary()->initHFShowerLibrary(iSetup);
0218 }
0219
0220
0221 myCalorimetry->initialize(_randomEngine.get());
0222 }
0223
0224
0225 std::vector<FSimTrack> myFSimTracks;
0226
0227 LogDebug(MESSAGECATEGORY) << "################################"
0228 << "\n###############################";
0229
0230
0231 for (std::unique_ptr<fastsim::Particle> particle = particleManager.nextParticle(*_randomEngine); particle != nullptr;
0232 particle = particleManager.nextParticle(*_randomEngine)) {
0233 LogDebug(MESSAGECATEGORY) << "\n moving NEXT particle: " << *particle;
0234
0235
0236
0237
0238
0239
0240
0241
0242 if (particle->position().Perp2() < 128. * 128. && std::abs(particle->position().Z()) < 302.) {
0243
0244 fastsim::LayerNavigator layerNavigator(geometry_);
0245 const fastsim::SimplifiedGeometry* layer = nullptr;
0246
0247
0248
0249 while (layerNavigator.moveParticleToNextLayer(*particle, layer)) {
0250 LogDebug(MESSAGECATEGORY) << " moved to next layer: " << *layer;
0251 LogDebug(MESSAGECATEGORY) << " new state: " << *particle;
0252
0253
0254
0255 if (layer->getCaloType() == fastsim::SimplifiedGeometry::TRACKERBOUNDARY) {
0256 layer = nullptr;
0257
0258 particle->resetOnLayer();
0259 break;
0260 }
0261
0262
0263 if (particle->position().T() > 25) {
0264 layer = nullptr;
0265
0266 particle->resetOnLayer();
0267 break;
0268 }
0269
0270
0271
0272 if (layer->getThickness(particle->position(), particle->momentum()) > 1E-10) {
0273 int nSecondaries = 0;
0274
0275 for (fastsim::InteractionModel* interactionModel : layer->getInteractionModels()) {
0276 LogDebug(MESSAGECATEGORY) << " interact with " << *interactionModel;
0277 std::vector<std::unique_ptr<fastsim::Particle> > secondaries;
0278 interactionModel->interact(*particle, *layer, secondaries, *_randomEngine);
0279 nSecondaries += secondaries.size();
0280 particleManager.addSecondaries(particle->position(), particle->simTrackIndex(), secondaries, layer);
0281 }
0282
0283
0284 if (!particleFilter_.acceptsEn(*particle)) {
0285
0286 if (nSecondaries == 0)
0287 particleManager.addEndVertex(particle.get());
0288 layer = nullptr;
0289 break;
0290 }
0291 }
0292
0293 LogDebug(MESSAGECATEGORY) << "--------------------------------"
0294 << "\n-------------------------------";
0295 }
0296
0297
0298 if (!particle->isStable() && particle->remainingProperLifeTimeC() < 1E-10) {
0299 LogDebug(MESSAGECATEGORY) << "Decaying particle...";
0300 std::vector<std::unique_ptr<fastsim::Particle> > secondaries;
0301 if (useFastSimsDecayer)
0302 decayer_.decay(*particle, secondaries, _randomEngine->theEngine());
0303 LogDebug(MESSAGECATEGORY) << " decay has " << secondaries.size() << " products";
0304 particleManager.addSecondaries(particle->position(), particle->simTrackIndex(), secondaries);
0305 continue;
0306 }
0307
0308 LogDebug(MESSAGECATEGORY) << "################################"
0309 << "\n###############################";
0310 }
0311
0312
0313
0314
0315
0316
0317
0318
0319 if (particle->position().Perp2() >= 128. * 128. || std::abs(particle->position().Z()) >= 302.) {
0320 LogDebug(MESSAGECATEGORY) << "\n moving particle to calorimetry: " << *particle;
0321
0322
0323 myFSimTracks.push_back(createFSimTrack(particle.get(), &particleManager, pdt));
0324
0325 if (!particle->isStable() && particle->remainingProperLifeTimeC() < 1E-10) {
0326 continue;
0327 }
0328
0329 LogDebug(MESSAGECATEGORY) << "################################"
0330 << "\n###############################";
0331 }
0332
0333
0334
0335
0336
0337 LogDebug(MESSAGECATEGORY) << "################################"
0338 << "\n###############################";
0339 }
0340
0341
0342 iEvent.put(std::move(simTracks_));
0343 iEvent.put(std::move(simVertices_));
0344
0345 for (auto& interactionModel : interactionModels_) {
0346 interactionModel->storeProducts(iEvent);
0347 }
0348
0349
0350
0351
0352 if (simulateCalorimetry) {
0353 for (auto myFSimTrack : myFSimTracks) {
0354 myCalorimetry->reconstructTrack(myFSimTrack, _randomEngine.get());
0355 }
0356 }
0357
0358
0359
0360
0361 std::unique_ptr<edm::PCaloHitContainer> p4(new edm::PCaloHitContainer);
0362 std::unique_ptr<edm::PCaloHitContainer> p5(new edm::PCaloHitContainer);
0363 std::unique_ptr<edm::PCaloHitContainer> p6(new edm::PCaloHitContainer);
0364 std::unique_ptr<edm::PCaloHitContainer> p7(new edm::PCaloHitContainer);
0365
0366 std::unique_ptr<edm::SimTrackContainer> m1(new edm::SimTrackContainer);
0367
0368 if (simulateCalorimetry) {
0369 myCalorimetry->loadFromEcalBarrel(*p4);
0370 myCalorimetry->loadFromEcalEndcap(*p5);
0371 myCalorimetry->loadFromPreshower(*p6);
0372 myCalorimetry->loadFromHcal(*p7);
0373 if (simulateMuons) {
0374 myCalorimetry->harvestMuonSimTracks(*m1);
0375 }
0376 }
0377 iEvent.put(std::move(p4), "EcalHitsEB");
0378 iEvent.put(std::move(p5), "EcalHitsEE");
0379 iEvent.put(std::move(p6), "EcalHitsES");
0380 iEvent.put(std::move(p7), "HcalHits");
0381 iEvent.put(std::move(m1), "MuonSimTracks");
0382 }
0383
0384 void FastSimProducer::endStream() { _randomEngine.reset(); }
0385
0386 FSimTrack FastSimProducer::createFSimTrack(fastsim::Particle* particle,
0387 fastsim::ParticleManager* particleManager,
0388 HepPDT::ParticleDataTable const& particleTable) {
0389 FSimTrack myFSimTrack(particle->pdgId(),
0390 particleManager->getSimTrack(particle->simTrackIndex()).momentum(),
0391 particle->simVertexIndex(),
0392 particle->genParticleIndex(),
0393 particle->simTrackIndex(),
0394 particle->charge(),
0395 particle->position(),
0396 particle->momentum(),
0397 particleManager->getSimVertex(particle->simVertexIndex()));
0398
0399
0400 fastsim::LayerNavigator caloLayerNavigator(caloGeometry_);
0401 const fastsim::SimplifiedGeometry* caloLayer = nullptr;
0402
0403
0404
0405 while (caloLayerNavigator.moveParticleToNextLayer(*particle, caloLayer)) {
0406 LogDebug(MESSAGECATEGORY) << " moved to next caloLayer: " << *caloLayer;
0407 LogDebug(MESSAGECATEGORY) << " new state: " << *particle;
0408
0409
0410 if (particle->position().T() > 50) {
0411 caloLayer = nullptr;
0412 break;
0413 }
0414
0415
0416
0417
0418
0419 RawParticle PP = makeParticle(&particleTable, particle->pdgId(), particle->momentum(), particle->position());
0420
0421
0422 if (caloLayer->getThickness(particle->position(), particle->momentum()) < 1E-10) {
0423
0424 if (caloLayer->getCaloType() == fastsim::SimplifiedGeometry::ECAL) {
0425 if (!myFSimTrack.onEcal()) {
0426 myFSimTrack.setEcal(PP, 0);
0427 }
0428 } else if (caloLayer->getCaloType() == fastsim::SimplifiedGeometry::HCAL) {
0429 if (!myFSimTrack.onHcal()) {
0430 myFSimTrack.setHcal(PP, 0);
0431 }
0432 } else if (caloLayer->getCaloType() == fastsim::SimplifiedGeometry::VFCAL) {
0433 if (!myFSimTrack.onVFcal()) {
0434 myFSimTrack.setVFcal(PP, 0);
0435 }
0436 }
0437
0438
0439 if (caloLayer->getCaloType() == fastsim::SimplifiedGeometry::VFCAL) {
0440 myFSimTrack.setGlobal();
0441 caloLayer = nullptr;
0442 break;
0443 }
0444
0445 continue;
0446 }
0447
0448
0449
0450 int success = 0;
0451 if (caloLayer->isForward()) {
0452 success = 2;
0453
0454 if (particle->position().Z() * particle->momentum().Z() < 0) {
0455 success *= -1;
0456 }
0457 } else {
0458 success = 1;
0459
0460 if (particle->momentum().X() * particle->position().X() + particle->momentum().Y() * particle->position().Y() <
0461 0) {
0462 success *= -1;
0463 }
0464 }
0465
0466
0467 if (caloLayer->getCaloType() == fastsim::SimplifiedGeometry::PRESHOWER1) {
0468 if (!myFSimTrack.onLayer1()) {
0469 myFSimTrack.setLayer1(PP, success);
0470 }
0471 }
0472
0473 if (caloLayer->getCaloType() == fastsim::SimplifiedGeometry::PRESHOWER2) {
0474 if (!myFSimTrack.onLayer2()) {
0475 myFSimTrack.setLayer2(PP, success);
0476 }
0477 }
0478
0479 if (caloLayer->getCaloType() == fastsim::SimplifiedGeometry::ECAL) {
0480 if (!myFSimTrack.onEcal()) {
0481 myFSimTrack.setEcal(PP, success);
0482 }
0483 }
0484
0485 if (caloLayer->getCaloType() == fastsim::SimplifiedGeometry::HCAL) {
0486 if (!myFSimTrack.onHcal()) {
0487 myFSimTrack.setHcal(PP, success);
0488 }
0489 }
0490
0491 if (caloLayer->getCaloType() == fastsim::SimplifiedGeometry::VFCAL) {
0492 if (!myFSimTrack.onVFcal()) {
0493 myFSimTrack.setVFcal(PP, success);
0494 }
0495 }
0496
0497
0498 if (caloLayer->getCaloType() == fastsim::SimplifiedGeometry::VFCAL) {
0499 myFSimTrack.setGlobal();
0500 caloLayer = nullptr;
0501 break;
0502 }
0503
0504 LogDebug(MESSAGECATEGORY) << "--------------------------------"
0505 << "\n-------------------------------";
0506 }
0507
0508
0509
0510
0511 if (!particle->isStable() && particle->remainingProperLifeTimeC() < 1E-10) {
0512 LogDebug(MESSAGECATEGORY) << "Decaying particle...";
0513 std::vector<std::unique_ptr<fastsim::Particle> > secondaries;
0514 if (useFastSimsDecayer)
0515 decayer_.decay(*particle, secondaries, _randomEngine->theEngine());
0516 LogDebug(MESSAGECATEGORY) << " decay has " << secondaries.size() << " products";
0517 particleManager->addSecondaries(particle->position(), particle->simTrackIndex(), secondaries);
0518 }
0519
0520 return myFSimTrack;
0521 }
0522
0523 DEFINE_FWK_MODULE(FastSimProducer);