Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-05 08:09:08

0001 // This file is part of the Acts project.
0002 //
0003 // Copyright (C) 2018 CERN for the benefit of the Acts project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
0008 
0009 #pragma once
0010 
0011 #include "Acts/EventData/NeutralParameters.hpp"
0012 #include "Acts/EventData/TrackParameters.hpp"
0013 #include "Acts/Propagator/AbortList.hpp"
0014 #include "Acts/Propagator/ActionList.hpp"
0015 #include "Acts/Propagator/Propagator.hpp"
0016 #include "Acts/Propagator/detail/DebugOutputActor.hpp"
0017 #include "Acts/Propagator/detail/StandardAborters.hpp"
0018 #include "Acts/Utilities/Logger.hpp"
0019 #include <optional>
0020 
0021 namespace Fatras {
0022 
0023 struct VoidDetector {};
0024 
0025 /// @brief Fatras simulator
0026 ///
0027 /// This is called from a Fatras steering algorithm
0028 /// Per call, the generator is provided which
0029 /// is then used to create a Acts propagator plugin.
0030 ///
0031 /// @tparam charged_propagator_t Type of the propagator for charged particles
0032 /// @tparam charged_selector_t Type of the slector (list) for charged particles
0033 /// @tparam charged_interactor_t Type of the dresser for chargerd particles
0034 ///
0035 /// @tparam neutral_propagator_t Type of the propagator for neutral particles
0036 /// @tparam neutral_selector_t Type of the slector (list) for neutral particles
0037 /// @tparam neutral_interactor_t Type of the dresser for neutral particles
0038 template <typename charged_propagator_t, typename charged_selector_t,
0039           typename charged_interactor_t, typename neutral_propagator_t,
0040           typename neutral_selector_t, typename neutral_interactor_t>
0041 struct Simulator {
0042 
0043   Simulator(charged_propagator_t chpropagator, neutral_propagator_t npropagator)
0044       : chargedPropagator(std::move(chpropagator)),
0045         neutralPropagator(std::move(npropagator)),
0046         mlogger(Acts::getDefaultLogger("Simulator", Acts::Logging::INFO)) {}
0047 
0048   using PhysicsList_t = typename charged_interactor_t::PhysicsList_t;
0049   charged_propagator_t chargedPropagator;
0050   charged_selector_t chargedSelector;
0051   PhysicsList_t physicsList;
0052 
0053   neutral_propagator_t neutralPropagator;
0054   neutral_selector_t neutralSelector;
0055 
0056   VoidDetector detector;
0057 
0058   std::shared_ptr<const Acts::Logger> mlogger = nullptr;
0059 
0060   bool debug = false;
0061 
0062   /// Private access to the logging instance
0063   const Acts::Logger &logger() const { return *mlogger; }
0064 
0065   /// @brief call operator to the simulator
0066   ///
0067   /// @tparam context_t Type pf the context object
0068   /// @tparam generator_t Type of the generator object
0069   /// @tparam event_collection_t Type of the event collection
0070   /// @tparam hit_collection_t Type of the hit collection, needs insert()
0071   ///
0072   /// @param fatrasContext is the event-bound context
0073   /// @param fatrasGenerator is the event-bound random generator
0074   /// @param fatrasEvent is the truth event collection
0075   /// @param fatrasHits is the hit collection
0076   template <typename context_t, typename generator_t,
0077             typename event_collection_t, typename hit_collection_t>
0078   void operator()(context_t &fatrasContext, generator_t &fatrasGenerator,
0079                   event_collection_t &fatrasEvent,
0080                   hit_collection_t &fatrasHits) const {
0081 
0082     // if screen output is required
0083     typedef Acts::detail::DebugOutputActor DebugOutput;
0084 
0085     // Action list, abort list and options
0086     typedef Acts::ActionList<charged_interactor_t, DebugOutput>
0087         ChargedActionList;
0088     typedef Acts::AbortList<Acts::detail::EndOfWorldReached> ChargedAbortList;
0089     typedef Acts::PropagatorOptions<ChargedActionList, ChargedAbortList>
0090         ChargedOptions;
0091 
0092     // Action list, abort list and
0093     typedef Acts::ActionList<neutral_interactor_t, DebugOutput>
0094         NeutralActionList;
0095     typedef Acts::AbortList<Acts::detail::EndOfWorldReached> NeutralAbortList;
0096     typedef Acts::PropagatorOptions<NeutralActionList, NeutralAbortList>
0097         NeutralOptions;
0098 
0099     // loop over the input events
0100     // -> new secondaries will just be attached to that
0101     for (auto &vertex : fatrasEvent) {
0102       // take care here, the simulation can change the
0103       // particle collection
0104       for (std::size_t i = 0; i < vertex.outgoing.size(); i++) {
0105         // create a local copy since the collection can reallocate and
0106         // invalidate any reference.
0107         auto particle = vertex.outgoing[i];
0108         // charged particle detected and selected
0109         if (chargedSelector(detector, particle)) {
0110           // Need to construct them per call to set the particle
0111           // Options and configuration
0112           ChargedOptions chargedOptions(fatrasContext.geoContext,
0113                                         fatrasContext.magFieldContext);
0114           chargedOptions.debug = debug;
0115           // Get the charged interactor
0116           auto &chargedInteractor =
0117               chargedOptions.actionList.template get<charged_interactor_t>();
0118           // Result type typedef
0119           typedef typename charged_interactor_t::result_type ChargedResult;
0120           // Set the generator to guarantee event consistent entires
0121           chargedInteractor.generator = &fatrasGenerator;
0122           // Put all the additional information into the interactor
0123           chargedInteractor.initialParticle = particle;
0124           // Set the physics list
0125           chargedInteractor.physicsList = physicsList;
0126           // Create the kinematic start parameters
0127           Acts::CurvilinearParameters start(std::nullopt, particle.position(),
0128                                             particle.momentum(), particle.q(),
0129                                             particle.time());
0130           // Run the simulation
0131           const auto &result =
0132               chargedPropagator.propagate(start, chargedOptions).value();
0133           const auto &fatrasResult = result.template get<ChargedResult>();
0134           // a) Handle the hits
0135           // hits go to the hit collection, particle go to the particle
0136           // collection
0137           for (const auto &fHit : fatrasResult.simulatedHits) {
0138             fatrasHits.insert(fHit);
0139           }
0140           // b) deal with the particles
0141           const auto &simparticles = fatrasResult.outgoing;
0142           vertex.outgoing_insert(simparticles);
0143           // c) screen output if requested
0144           if (debug) {
0145             auto &fatrasDebug = result.template get<DebugOutput::result_type>();
0146             ACTS_INFO(fatrasDebug.debugString);
0147           }
0148         } else if (neutralSelector(detector, particle)) {
0149           // Options and configuration
0150           NeutralOptions neutralOptions(fatrasContext.geoContext,
0151                                         fatrasContext.magFieldContext);
0152           neutralOptions.debug = debug;
0153           // Get the charged interactor
0154           auto &neutralInteractor =
0155               neutralOptions.actionList.template get<neutral_interactor_t>();
0156           // Result type typedef
0157           typedef typename neutral_interactor_t::result_type NeutralResult;
0158           // Set the generator to guarantee event consistent entires
0159           neutralInteractor.generator = &fatrasGenerator;
0160           // Put all the additional information into the interactor
0161           neutralInteractor.initialParticle = particle;
0162           // Create the kinematic start parameters
0163           Acts::NeutralCurvilinearParameters start(
0164               std::nullopt, particle.position(), particle.momentum(), 0.);
0165           const auto &result =
0166               neutralPropagator.propagate(start, neutralOptions).value();
0167           auto &fatrasResult = result.template get<NeutralResult>();
0168           // a) deal with the particles
0169           const auto &simparticles = fatrasResult.outgoing;
0170           vertex.outgoing_insert(simparticles);
0171           // b) screen output if requested
0172           if (debug) {
0173             auto &fatrasDebug = result.template get<DebugOutput::result_type>();
0174             ACTS_INFO(fatrasDebug.debugString);
0175           }
0176         } // neutral processing
0177       }   // loop over particles
0178     }     // loop over events
0179   }
0180 };
0181 
0182 } // namespace Fatras