All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
IonAndScint_module.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 // Class: IonAndScint
3 // Plugin Type: producer
4 // File: IonAndScint_module.cc
5 // Description:
6 // - acts on sim::SimEnergyDeposit from LArG4Main,
7 // - calculate the number of photons and electrons
8 // Input: 'sim::SimEnergyDeposit'
9 // Output: updated 'sim::SimEnergyDeposit' with numPhotons and numElectrons
10 //
11 //This module calculate the number of photons and electrons produced at each step where energy is deposited.
12 //The Separate algorithm is used by default, but this can be changed via the "ISCalcAlg"
13 //fhicl parameter tag.
14 //At the end of this module the numPhotons and numElectrons of sim:SimEnergyDeposit have been updated.
15 //
16 // Aug.18 by Mu Wei
17 //
18 // 10/28/2019 Wenqiang Gu (wgu@bnl.gov)
19 // Add the Space Charge Effect (SCE) if the option is enabled
20 ////////////////////////////////////////////////////////////////////////
21 
22 // LArSoft includes
23 
32 
33 #include "nurandom/RandomUtils/NuRandomService.h"
34 
35 // Framework includes
36 #include "art/Framework/Core/EDProducer.h"
37 #include "art/Framework/Core/ModuleMacros.h"
38 #include "art/Framework/Principal/Event.h"
39 #include "art/Framework/Principal/Handle.h"
40 #include "art/Framework/Principal/Selector.h"
41 #include "art/Framework/Services/Registry/ServiceHandle.h"
42 #include "messagefacility/MessageLogger/MessageLogger.h"
43 #include "fhiclcpp/ParameterSet.h"
44 #include "canvas/Utilities/Exception.h"
45 #include "canvas/Utilities/InputTag.h"
46 
47 #include "CLHEP/Random/RandomEngine.h"
48 
49 #include <iostream>
50 #include <sstream> // std::stringstream
51 #include <string>
52 #include <vector>
53 
54 using std::string;
55 using SimEnergyDepositCollection = std::vector<sim::SimEnergyDeposit>;
56 
57 namespace larg4 {
58  class IonAndScint : public art::EDProducer {
59  public:
60  explicit IonAndScint(fhicl::ParameterSet const& pset);
61  void produce(art::Event& event) override;
62  void beginJob() override;
63  void endJob() override;
64 
65  private:
66 
67  std::vector<art::Handle<SimEnergyDepositCollection>> inputCollections(art::Event const&) const;
68 
69  // name of calculator: Separate, Correlated, or NEST
70  art::InputTag calcTag;
71 
72  // The input module labels to specify which SimEnergyDeposit
73  // collections to use as input. Specify only the module label,
74  // not the instance name(s). Instances to be used have to be
75  // passed via the Instances parameter.
76  // If empty, this module uses all the available collections.
77  std::vector<std::string> fInputModuleLabels;
78 
79  std::unique_ptr<ISCalc> fISAlg;
80  CLHEP::HepRandomEngine& fEngine;
81  string Instances;
82  std::vector<string> instanceNames;
84  };
85 
86  //......................................................................
87  IonAndScint::IonAndScint(fhicl::ParameterSet const& pset)
88  : art::EDProducer{pset}
89  , calcTag{pset.get<art::InputTag>("ISCalcAlg")}
90  , fInputModuleLabels{pset.get<std::vector<std::string>>("InputModuleLabels", {})}
91  , fEngine(art::ServiceHandle<rndm::NuRandomService>()
92  ->createEngine(*this, "HepJamesRandom", "ISCalcAlg", pset, "SeedISCalcAlg"))
94  pset.get<string>("Instances", "LArG4DetectorServicevolTPCActive"),
95  }
96  , fSavePriorSCE{pset.get<bool>("SavePriorSCE", false)}
97  {
98  std::cout << "IonAndScint Module Construct" << std::endl;
99 
100  if (Instances.empty()) {
101  std::cout << "Produce SimEnergyDeposit in default volume - LArG4DetectorServicevolTPCActive"
102  << std::endl;
103  instanceNames.push_back("LArG4DetectorServicevolTPCActive");
104  }
105  else {
106  std::stringstream input(Instances);
107  string temp;
108  while (std::getline(input, temp, ';')) {
109  instanceNames.push_back(temp);
110  }
111 
112  std::cout << "Produce SimEnergyDeposit in volumes: " << std::endl;
113  for (auto instanceName : instanceNames) {
114  std::cout << " - " << instanceName << std::endl;
115  }
116  }
117 
118  produces<std::vector<sim::SimEnergyDeposit>>();
119  if (fSavePriorSCE) produces<std::vector<sim::SimEnergyDeposit>>("priorSCE");
120  }
121 
122  //......................................................................
123  void
125  {
126  std::cout << "IonAndScint beginJob." << std::endl;
127  std::cout << "Using " << calcTag.label() << " algorithm to calculate IS." << std::endl;
128 
129  if (calcTag.label() == "Separate")
130  fISAlg = std::make_unique<ISCalcSeparate>();
131  else if (calcTag.label() == "Correlated") {
132  auto const detProp = art::ServiceHandle<detinfo::DetectorPropertiesService>()->DataForJob();
133  fISAlg = std::make_unique<ISCalcCorrelated>(detProp, fEngine);
134  }
135  else if (calcTag.label() == "NEST")
136  fISAlg = std::make_unique<ISCalcNESTLAr>(fEngine);
137  else
138  mf::LogWarning("IonAndScint") << "No ISCalculation set, this can't be good.";
139  }
140 
141  //......................................................................
142  void
144  {
145  std::cout << "IonAndScint endJob." << std::endl;
146  }
147 
148  //......................................................................
149  std::vector<art::Handle<SimEnergyDepositCollection>>
150  IonAndScint::inputCollections(art::Event const& e) const
151  {
152  if (empty(fInputModuleLabels)) {
153  mf::LogDebug("IonAndScint") << "Retrieving all products" << std::endl;
154  return e.getMany<SimEnergyDepositCollection>();
155  }
156 
157  std::vector<art::Handle<SimEnergyDepositCollection>> result;
158 
159  for (auto const & module : fInputModuleLabels) {
160 
161  mf::LogDebug("IonAndScint") << "Retrieving products with module label "
162  << module << std::endl;
163 
164  auto handels = e.getMany<SimEnergyDepositCollection>(art::ModuleLabelSelector(module));
165 
166  if (empty(handels)) {
167  throw art::Exception(art::errors::ProductNotFound)
168  << "IonAndScint module cannot find any SimEnergyDeposits with module label "
169  << module << " as requested in InputModuleLabels. \n";
170  }
171 
172  result.insert(result.end(), handels.begin(), handels.end());
173  }
174 
175  return result;
176  }
177 
178  //......................................................................
179  void
180  IonAndScint::produce(art::Event& event)
181  {
182  std::cout << "IonAndScint Module Producer" << std::endl;
183 
184  std::vector<art::Handle<SimEnergyDepositCollection>> edepHandle = inputCollections(event);
185 
186  if (empty(edepHandle)) {
187  std::cout << "IonAndScint Module Cannot Retrive SimEnergyDeposit" << std::endl;
188  return;
189  }
190 
191  auto sce = lar::providerFrom<spacecharge::SpaceChargeService>();
192  auto const detProp =
193  art::ServiceHandle<detinfo::DetectorPropertiesService const>()->DataFor(event);
194 
195  auto simedep = std::make_unique<std::vector<sim::SimEnergyDeposit>>();
196  auto simedep1 = std::make_unique<std::vector<sim::SimEnergyDeposit>>(); // for prior-SCE depos
197  for (auto edeps : edepHandle) {
198  // Do some checking before we proceed
199  if (!edeps.isValid()) {
200  std::cout << "!edeps.isValid()" << std::endl;
201  continue;
202  }
203 
204  auto index = std::find(
205  instanceNames.begin(), instanceNames.end(), edeps.provenance()->productInstanceName());
206  if (index == instanceNames.end()) {
207  std::cout << "Skip SimEnergyDeposit in: " << edeps.provenance()->productInstanceName()
208  << std::endl;
209  continue;
210  }
211 
212  std::cout << "SimEnergyDeposit input module: " << edeps.provenance()->moduleLabel()
213  << ", instance name: " << edeps.provenance()->productInstanceName() << std::endl;
214 
215  for (sim::SimEnergyDeposit const& edepi : *edeps) {
216  auto const isCalcData = fISAlg->CalcIonAndScint(detProp, edepi);
217 
218  int ph_num = round(isCalcData.numPhotons);
219  int ion_num = round(isCalcData.numElectrons);
220  float scintyield = isCalcData.scintillationYieldRatio;
221  float edep_tmp = edepi.Energy();
222  geo::Point_t startPos_tmp = edepi.Start();
223  geo::Point_t endPos_tmp = edepi.End();
224  double startTime_tmp = edepi.StartT();
225  double endTime_tmp = edepi.EndT();
226  int trackID_tmp = edepi.TrackID();
227  int pdgCode_tmp = edepi.PdgCode();
228 
229  if (sce->EnableSimSpatialSCE()) {
230  auto posOffsetsStart =
231  sce->GetPosOffsets({edepi.StartX(), edepi.StartY(), edepi.StartZ()});
232  auto posOffsetsEnd = sce->GetPosOffsets({edepi.EndX(), edepi.EndY(), edepi.EndZ()});
233  startPos_tmp =
234  geo::Point_t{(float)(edepi.StartX() - posOffsetsStart.X()), //x should be subtracted
235  (float)(edepi.StartY() + posOffsetsStart.Y()),
236  (float)(edepi.StartZ() + posOffsetsStart.Z())};
237  endPos_tmp =
238  geo::Point_t{(float)(edepi.EndX() - posOffsetsEnd.X()), //x should be subtracted
239  (float)(edepi.EndY() + posOffsetsEnd.Y()),
240  (float)(edepi.EndZ() + posOffsetsEnd.Z())};
241  }
242 
243  simedep->emplace_back(ph_num,
244  ion_num,
245  scintyield,
246  edep_tmp,
247  startPos_tmp,
248  endPos_tmp,
249  startTime_tmp,
250  endTime_tmp,
251  trackID_tmp,
252  pdgCode_tmp);
253 
254  if (fSavePriorSCE) {
255  simedep1->emplace_back(ph_num,
256  ion_num,
257  scintyield,
258  edepi.Energy(),
259  edepi.Start(),
260  edepi.End(),
261  edepi.StartT(),
262  edepi.EndT(),
263  edepi.TrackID(),
264  edepi.PdgCode());
265  }
266 
267  }
268  }
269  event.put(std::move(simedep));
270  if (fSavePriorSCE) event.put(std::move(simedep1), "priorSCE");
271  }
272 } // namespace
273 DEFINE_ART_MODULE(larg4::IonAndScint)
void beginJob() override
Utilities related to art service access.
IonAndScint(fhicl::ParameterSet const &pset)
CLHEP::HepRandomEngine & fEngine
std::vector< art::Handle< SimEnergyDepositCollection > > inputCollections(art::Event const &) const
std::vector< std::string > fInputModuleLabels
fEngine(art::ServiceHandle< rndm::NuRandomService >() ->createEngine(*this,"HepJamesRandom","ISCalcAlg", pset,"SeedISCalcAlg"))
std::vector< string > instanceNames
void endJob() override
contains information for a single step in the detector simulation
Energy deposition in the active material.
do i e
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< double >, ROOT::Math::GlobalCoordinateSystemTag > Point_t
Type for representation of position in physical 3D space.
Definition: geo_vectors.h:184
std::unique_ptr< ISCalc > fISAlg
bool empty(FixedBins< T, C > const &) noexcept
Definition: FixedBins.h:555
void produce(art::Event &event) override
BEGIN_PROLOG could also be cout
auto const detProp
std::vector< sim::SimEnergyDeposit > SimEnergyDepositCollection